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 RecursiveASTVisitor
<StdException
>, public loplugin::RewritePlugin
29 explicit StdException(InstantiationData
const & data
): RewritePlugin(data
)
32 virtual void run() override
33 { TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
35 bool VisitCXXMethodDecl(CXXMethodDecl
const * decl
);
38 bool isInMainFile(SourceLocation spellingLocation
) const;
41 bool StdException::VisitCXXMethodDecl(CXXMethodDecl
const * decl
) {
42 if (ignoreLocation(decl
)
43 || decl
->begin_overridden_methods() == decl
->end_overridden_methods())
47 CXXMethodDecl
const * over
= nullptr;
48 for (auto i
= decl
->begin_overridden_methods();
49 i
!= decl
->end_overridden_methods(); ++i
)
51 FunctionProtoType
const * t
52 = (*i
)->getType()->getAs
<FunctionProtoType
>();
53 switch (t
->getExceptionSpecType()) {
57 case EST_BasicNoexcept
:
61 unsigned n
= t
->getNumExceptions();
62 for (unsigned j
= 0; j
!= n
; ++j
) {
63 if (isStdException(t
->getExceptionType(j
))) {
70 case EST_ComputedNoexcept
:
71 switch (t
->getNoexceptSpec(compiler
.getASTContext())) {
72 case FunctionProtoType::NR_NoNoexcept
:
73 case FunctionProtoType::NR_BadNoexcept
:
76 case FunctionProtoType::NR_Dependent
:
78 case FunctionProtoType::NR_Throw
:
80 case FunctionProtoType::NR_Nothrow
:
85 case EST_Uninstantiated
:
91 FunctionProtoType
const * t
= decl
->getType()->getAs
<FunctionProtoType
>();
92 if (!t
->hasDynamicExceptionSpec()) {
94 DiagnosticsEngine::Warning
,
95 "override does not have dynamic exception specification",
97 << decl
->getSourceRange();
99 DiagnosticsEngine::Note
,
100 ("overridden declaration with dynamic exception specification"
101 " including std::exception is here"),
102 over
->getLocStart());
105 unsigned n
= t
->getNumExceptions();
106 for (unsigned i
= 0; i
!= n
; ++i
) {
107 if (isStdException(t
->getExceptionType(i
))) {
111 SourceRange r
{ decl
->getSourceRange() };
113 compiler
.getSourceManager().getExpansionLoc(r
.getBegin()) };
115 compiler
.getSourceManager().getExpansionLoc(r
.getEnd()) };
118 || compiler
.getSourceManager().isBeforeInTranslationUnit(l
, end
));
119 bool seenThrow
= false;
121 SourceLocation openParen
;
124 unsigned n
= Lexer::MeasureTokenLength(
125 l
, compiler
.getSourceManager(), compiler
.getLangOpts());
126 std::string s
{ compiler
.getSourceManager().getCharacterData(l
), n
};
127 if (s
== "{" || s
== ";") {
134 } else if (s
== "(") {
135 assert(parens
< std::numeric_limits
<unsigned>::max());
141 } else if (s
== ")") {
145 assert(loc
.isValid());
146 // Only rewrite declarations in include files if a definition is
147 // also seen, to avoid compilation of a definition (in a main
148 // file only processed later) to fail with a "mismatch" error
149 // before the rewriter had a chance to act upon the definition
150 // (but use the heuristic of assuming pure virtual functions do
151 // not have definitions):
152 if (rewriter
!= nullptr
154 compiler
.getSourceManager().getSpellingLoc(loc
))
155 || decl
->isDefined() || decl
->isPure())
156 && insertTextAfterToken(
159 ? "std::exception" : ", std::exception")))
166 } else if (!s
.empty() && s
.compare(0, 2, "/*") != 0
167 && s
.compare(0, 2, "//") != 0)
174 l
= l
.getLocWithOffset(std::max
<unsigned>(n
, 1));
177 DiagnosticsEngine::Warning
,
178 "override dropped std::exception from dynamic exception specification",
179 openParen
.isValid() ? openParen
: decl
->getLocStart())
180 << decl
->getSourceRange();
182 DiagnosticsEngine::Note
, "overridden declaration is here",
183 over
->getLocStart());
187 bool StdException::isInMainFile(SourceLocation spellingLocation
) const {
188 #if (__clang_major__ == 3 && __clang_minor__ >= 4) || __clang_major__ > 3
189 return compiler
.getSourceManager().isInMainFile(spellingLocation
);
191 return compiler
.getSourceManager().isFromMainFile(spellingLocation
);
195 loplugin::Plugin::Registration
<StdException
> X("stdexception", true);
199 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */