1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
19 bool isStdException(QualType type
) {
21 std::string name
{ type
.getAsString() };
22 return name
== "std::exception" || name
== "::std::exception";
26 public loplugin::FilteringRewritePlugin
<StdException
>
29 explicit StdException(InstantiationData
const & data
): FilteringRewritePlugin(data
)
32 virtual void run() override
33 { TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
35 bool VisitCXXMethodDecl(CXXMethodDecl
const * decl
);
38 bool StdException::VisitCXXMethodDecl(CXXMethodDecl
const * decl
) {
39 if (ignoreLocation(decl
)
40 || decl
->begin_overridden_methods() == decl
->end_overridden_methods())
44 CXXMethodDecl
const * over
= nullptr;
45 for (auto i
= decl
->begin_overridden_methods();
46 i
!= decl
->end_overridden_methods(); ++i
)
48 FunctionProtoType
const * t
49 = (*i
)->getType()->getAs
<FunctionProtoType
>();
50 switch (t
->getExceptionSpecType()) {
54 case EST_BasicNoexcept
:
58 unsigned n
= t
->getNumExceptions();
59 for (unsigned j
= 0; j
!= n
; ++j
) {
60 if (isStdException(t
->getExceptionType(j
))) {
67 case EST_ComputedNoexcept
:
68 switch (t
->getNoexceptSpec(compiler
.getASTContext())) {
69 case FunctionProtoType::NR_NoNoexcept
:
70 case FunctionProtoType::NR_BadNoexcept
:
73 case FunctionProtoType::NR_Dependent
:
75 case FunctionProtoType::NR_Throw
:
77 case FunctionProtoType::NR_Nothrow
:
82 case EST_Uninstantiated
:
88 FunctionProtoType
const * t
= decl
->getType()->getAs
<FunctionProtoType
>();
89 if (!t
->hasDynamicExceptionSpec()) {
91 DiagnosticsEngine::Warning
,
92 "override does not have dynamic exception specification",
94 << decl
->getSourceRange();
96 DiagnosticsEngine::Note
,
97 ("overridden declaration with dynamic exception specification"
98 " including std::exception is here"),
102 unsigned n
= t
->getNumExceptions();
103 for (unsigned i
= 0; i
!= n
; ++i
) {
104 if (isStdException(t
->getExceptionType(i
))) {
108 SourceRange r
{ decl
->getSourceRange() };
110 compiler
.getSourceManager().getExpansionLoc(r
.getBegin()) };
112 compiler
.getSourceManager().getExpansionLoc(r
.getEnd()) };
115 || compiler
.getSourceManager().isBeforeInTranslationUnit(l
, end
));
116 bool seenThrow
= false;
118 SourceLocation openParen
;
121 unsigned n
= Lexer::MeasureTokenLength(
122 l
, compiler
.getSourceManager(), compiler
.getLangOpts());
123 std::string s
{ compiler
.getSourceManager().getCharacterData(l
), n
};
124 if (s
== "{" || s
== ";") {
131 } else if (s
== "(") {
132 assert(parens
< std::numeric_limits
<unsigned>::max());
138 } else if (s
== ")") {
142 assert(loc
.isValid());
143 // Only rewrite declarations in include files if a definition is
144 // also seen, to avoid compilation of a definition (in a main
145 // file only processed later) to fail with a "mismatch" error
146 // before the rewriter had a chance to act upon the definition
147 // (but use the heuristic of assuming pure virtual functions do
148 // not have definitions):
149 if (rewriter
!= nullptr
150 && (compiler
.getSourceManager().isInMainFile(
151 compiler
.getSourceManager().getSpellingLoc(loc
))
152 || decl
->isDefined() || decl
->isPure())
153 && insertTextAfterToken(
156 ? "std::exception" : ", std::exception")))
163 } else if (!s
.empty() && s
.compare(0, 2, "/*") != 0
164 && s
.compare(0, 2, "//") != 0)
171 l
= l
.getLocWithOffset(std::max
<unsigned>(n
, 1));
174 DiagnosticsEngine::Warning
,
175 "override dropped std::exception from dynamic exception specification",
176 openParen
.isValid() ? openParen
: decl
->getLocStart())
177 << decl
->getSourceRange();
179 DiagnosticsEngine::Note
, "overridden declaration is here",
180 over
->getLocStart());
184 loplugin::Plugin::Registration
<StdException
> X("stdexception", true);
188 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */