1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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/.
10 #ifndef LO_CLANG_SHARED_PLUGINS
15 // Find variable declarations at namespace scope that need not have external
20 // It looks like Clang wrongly implements DR 4
21 // (<http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#4>) and treats
22 // a variable declared in an 'extern "..." {...}'-style linkage-specification as
23 // if it contained the 'extern' specifier:
24 bool hasExternalLinkage(VarDecl
const * decl
) {
25 if (decl
->getLinkageAndVisibility().getLinkage() != ExternalLinkage
) {
28 for (auto ctx
= decl
->getLexicalDeclContext();
29 ctx
->getDeclKind() != Decl::TranslationUnit
;
30 ctx
= ctx
->getLexicalParent())
32 if (auto ls
= dyn_cast
<LinkageSpecDecl
>(ctx
)) {
33 if (!ls
->hasBraces()) {
36 if (auto prev
= decl
->getPreviousDecl()) {
37 return hasExternalLinkage(prev
);
39 return !decl
->isInAnonymousNamespace();
45 class ExternVar
: public loplugin::FilteringPlugin
<ExternVar
>
48 explicit ExternVar(loplugin::InstantiationData
const & data
): FilteringPlugin(data
)
52 { TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
54 bool VisitVarDecl(VarDecl
const * decl
) {
55 if (ignoreLocation(decl
)) {
58 if (decl
->isStaticDataMember()) {
61 if (!(decl
->isFirstDecl()
62 && compiler
.getSourceManager().isInMainFile(decl
->getLocation())
63 && hasExternalLinkage(decl
)))
67 auto def
= decl
->getDefinition();
71 // namespace { extern int v; }
72 // int f() { return sizeof(v); }
74 // is already handled by Clang itself with an error "variable 'v' is
75 // not needed and will not be emitted"
78 if (loplugin::DeclCheck(def
).Var("_pRawDllMain").GlobalNamespace()) {
81 SourceLocation argLoc
;
82 if (compiler
.getSourceManager().isMacroArgExpansion(def
->getLocation(), &argLoc
)
83 && (Lexer::getImmediateMacroName(
84 argLoc
, compiler
.getSourceManager(), compiler
.getLangOpts())
90 DiagnosticsEngine::Warning
,
91 "variable with external linkage not declared in an include file",
93 << def
->getSourceRange();
95 DiagnosticsEngine::Note
,
96 ("should either have internal linkage or be declared in an include"
99 << def
->getSourceRange();
100 for (auto prev
= def
;;) {
101 prev
= prev
->getPreviousDecl();
102 if (prev
== nullptr) {
106 DiagnosticsEngine::Note
, "previously declared here",
108 << prev
->getSourceRange();
114 loplugin::Plugin::Registration
<ExternVar
> externvar("externvar");
118 #endif // LO_CLANG_SHARED_PLUGINS
120 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */