/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GlobalVariableInitializationChecker.h" #include "CustomMatchers.h" void GlobalVariableInitializationChecker::registerMatchers(MatchFinder *AstMatcher) { auto FirstPartyGlobalVariable = varDecl( hasGlobalStorage(), unless(hasDeclContext(functionDecl())), allOf(isDefinition(), isFirstParty(), unless(isExpansionInSystemHeader())) ); auto FirstPartyGlobalVariableWithRuntimeInit = varDecl(FirstPartyGlobalVariable, allOf(anyOf(isConstexpr(), hasConstInitAttr(), hasConstantInitializer(), hasMozGlobalType()), isMozGlobal()), unless(isMozGenerated()) ); AstMatcher->addMatcher(FirstPartyGlobalVariableWithRuntimeInit.bind("flagged-constinit_global"), this); auto FirstPartyGlobalVariableWithoutAnnotation = varDecl( FirstPartyGlobalVariable, unless(anyOf(isConstexpr(), hasConstInitAttr(), isMozGlobal(), hasConstantInitializer(), hasMozGlobalType())) ); AstMatcher->addMatcher(FirstPartyGlobalVariableWithoutAnnotation.bind("non-constinit_global"), this); } void GlobalVariableInitializationChecker::check( const MatchFinder::MatchResult &Result) { if (const VarDecl *VD = Result.Nodes.getNodeAs("flagged-constinit_global")) { if (VD->hasConstantInitialization()) { diag(VD->getBeginLoc(), "Global variable flagged as MOZ_RUNINIT but actually has constinit initialisation. Consider flagging it as constexpr or MOZ_CONSTINIT instead.", DiagnosticIDs::Error); } else { 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.", DiagnosticIDs::Error); } } if (const VarDecl *VD = Result.Nodes.getNodeAs("non-constinit_global")) { const SourceManager &SM = VD->getASTContext().getSourceManager(); SourceLocation Loc = VD->getLocation(); // Some macro from third party end up triggering warning, we can't fix that // easily so ignore them. if (SM.isMacroBodyExpansion(Loc)) return; // FIXME: This captures some generated third party source, e.g. from // google-protocol, that are generated by third-party generators but are not // captured by `isFirstParty`, but may also catch some sources we own. if (getFilename(SM, Loc).ends_with(".cc")) { return; } diag(VD->getBeginLoc(), "Global variable has runtime initialisation, try to remove it, make it constexpr or MOZ_CONSTINIT if possible, or as a last resort flag it as MOZ_RUNINIT.", DiagnosticIDs::Error); } }