GlobalVariableInitializationChecker.cpp (2837B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "GlobalVariableInitializationChecker.h" 6 #include "CustomMatchers.h" 7 8 void GlobalVariableInitializationChecker::registerMatchers(MatchFinder *AstMatcher) { 9 auto FirstPartyGlobalVariable = varDecl( 10 hasGlobalStorage(), 11 unless(hasDeclContext(functionDecl())), 12 allOf(isDefinition(), isFirstParty(), unless(isExpansionInSystemHeader())) 13 ); 14 15 auto FirstPartyGlobalVariableWithRuntimeInit = varDecl(FirstPartyGlobalVariable, 16 allOf(anyOf(isConstexpr(), hasConstInitAttr(), hasConstantInitializer(), hasMozGlobalType()), isMozGlobal()), 17 unless(isMozGenerated()) 18 ); 19 20 AstMatcher->addMatcher(FirstPartyGlobalVariableWithRuntimeInit.bind("flagged-constinit_global"), this); 21 22 auto FirstPartyGlobalVariableWithoutAnnotation = varDecl( 23 FirstPartyGlobalVariable, 24 unless(anyOf(isConstexpr(), hasConstInitAttr(), isMozGlobal(), hasConstantInitializer(), hasMozGlobalType())) 25 ); 26 27 AstMatcher->addMatcher(FirstPartyGlobalVariableWithoutAnnotation.bind("non-constinit_global"), this); 28 } 29 30 void GlobalVariableInitializationChecker::check( 31 const MatchFinder::MatchResult &Result) { 32 if (const VarDecl *VD = 33 Result.Nodes.getNodeAs<VarDecl>("flagged-constinit_global")) { 34 if (VD->hasConstantInitialization()) { 35 diag(VD->getBeginLoc(), "Global variable flagged as MOZ_RUNINIT but actually has constinit initialisation. Consider flagging it as constexpr or constinit instead.", 36 DiagnosticIDs::Error); 37 } 38 else { 39 diag(VD->getBeginLoc(), "Global variable flagged as MOZ_RUNINIT but actually has constant initialisation. Consider removing the annotation or (as a last resort) flagging it as MOZ_GLOBINIT.", 40 DiagnosticIDs::Error); 41 } 42 } 43 44 if (const VarDecl *VD = 45 Result.Nodes.getNodeAs<VarDecl>("non-constinit_global")) { 46 const SourceManager &SM = VD->getASTContext().getSourceManager(); 47 48 SourceLocation Loc = VD->getLocation(); 49 50 // Some macro from third party end up triggering warning, we can't fix that 51 // easily so ignore them. 52 if (SM.isMacroBodyExpansion(Loc)) 53 return; 54 55 // FIXME: This captures some generated third party source, e.g. from 56 // google-protocol, that are generated by third-party generators but are not 57 // captured by `isFirstParty`, but may also catch some sources we own. 58 if (getFilename(SM, Loc).ends_with(".cc")) { 59 return; 60 } 61 diag(VD->getBeginLoc(), "Global variable has runtime initialisation, try to remove it, make it constexpr or constinit if possible, or as a last resort flag it as MOZ_RUNINIT.", 62 DiagnosticIDs::Error); 63 } 64 }