diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Basic/Diagnostic.cpp | 108 | ||||
-rw-r--r-- | clang/lib/Basic/DiagnosticIDs.cpp | 46 | ||||
-rw-r--r-- | clang/lib/Basic/SourceLocation.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Lex/MacroInfo.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Lex/PPDirectives.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Lex/PPExpressions.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Lex/PPLexerChange.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Lex/PPMacroExpansion.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Lex/Pragma.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Sema/AnalysisBasedWarnings.cpp | 25 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 2 |
17 files changed, 230 insertions, 83 deletions
diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp index 5098c2e4f8f..919ba8187ec 100644 --- a/clang/lib/Basic/Diagnostic.cpp +++ b/clang/lib/Basic/Diagnostic.cpp @@ -49,9 +49,10 @@ Diagnostic::Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &diags, ErrorLimit = 0; TemplateBacktraceLimit = 0; - // Set all mappings to 'unset'. - DiagMappingsStack.clear(); - DiagMappingsStack.push_back(DiagMappings()); + // Create a DiagState and DiagStatePoint representing diagnostic changes + // through command-line. + DiagStates.push_back(DiagState()); + PushDiagStatePoint(&DiagStates.back(), SourceLocation()); Reset(); } @@ -62,17 +63,19 @@ Diagnostic::~Diagnostic() { } -void Diagnostic::pushMappings() { - // Avoids undefined behavior when the stack has to resize. - DiagMappingsStack.reserve(DiagMappingsStack.size() + 1); - DiagMappingsStack.push_back(DiagMappingsStack.back()); +void Diagnostic::pushMappings(SourceLocation Loc) { + DiagStateOnPushStack.push_back(GetCurDiagState()); } -bool Diagnostic::popMappings() { - if (DiagMappingsStack.size() == 1) +bool Diagnostic::popMappings(SourceLocation Loc) { + if (DiagStateOnPushStack.empty()) return false; - DiagMappingsStack.pop_back(); + if (DiagStateOnPushStack.back() != GetCurDiagState()) { + // State changed at some point between push/pop. + PushDiagStatePoint(DiagStateOnPushStack.back(), Loc); + } + DiagStateOnPushStack.pop_back(); return true; } @@ -109,6 +112,91 @@ void Diagnostic::ReportDelayed() { DelayedDiagArg2.clear(); } +Diagnostic::DiagStatePointsTy::iterator +Diagnostic::GetDiagStatePointForLoc(SourceLocation L) const { + assert(!DiagStatePoints.empty()); + assert(DiagStatePoints.front().Loc.isInvalid() && + "Should have created a DiagStatePoint for command-line"); + + FullSourceLoc Loc(L, *SourceMgr); + if (Loc.isInvalid()) + return DiagStatePoints.end() - 1; + + DiagStatePointsTy::iterator Pos = DiagStatePoints.end(); + FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc; + if (LastStateChangePos.isValid() && + Loc.isBeforeInTranslationUnitThan(LastStateChangePos)) + Pos = std::upper_bound(DiagStatePoints.begin(), DiagStatePoints.end(), + DiagStatePoint(0, Loc)); + --Pos; + return Pos; +} + +/// \brief This allows the client to specify that certain +/// warnings are ignored. Notes can never be mapped, errors can only be +/// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily. +/// +/// \param The source location that this change of diagnostic state should +/// take affect. It can be null if we are setting the latest state. +void Diagnostic::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, + SourceLocation L) { + assert(Diag < diag::DIAG_UPPER_LIMIT && + "Can only map builtin diagnostics"); + assert((Diags->isBuiltinWarningOrExtension(Diag) || + (Map == diag::MAP_FATAL || Map == diag::MAP_ERROR)) && + "Cannot map errors into warnings!"); + assert(!DiagStatePoints.empty()); + + FullSourceLoc Loc(L, *SourceMgr); + FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc; + + // Common case; setting all the diagnostics of a group in one place. + if (Loc.isInvalid() || Loc == LastStateChangePos) { + setDiagnosticMappingInternal(Diag, Map, GetCurDiagState(), true); + return; + } + + // Another common case; modifying diagnostic state in a source location + // after the previous one. + if ((Loc.isValid() && LastStateChangePos.isInvalid()) || + LastStateChangePos.isBeforeInTranslationUnitThan(Loc)) { + // A diagnostic pragma occured, create a new DiagState initialized with + // the current one and a new DiagStatePoint to record at which location + // the new state became active. + DiagStates.push_back(*GetCurDiagState()); + PushDiagStatePoint(&DiagStates.back(), Loc); + setDiagnosticMappingInternal(Diag, Map, GetCurDiagState(), true); + return; + } + + // We allow setting the diagnostic state in random source order for + // completeness but it should not be actually happening in normal practice. + + DiagStatePointsTy::iterator Pos = GetDiagStatePointForLoc(Loc); + assert(Pos != DiagStatePoints.end()); + + // Update all diagnostic states that are active after the given location. + for (DiagStatePointsTy::iterator + I = Pos+1, E = DiagStatePoints.end(); I != E; ++I) { + setDiagnosticMappingInternal(Diag, Map, I->State, true); + } + + // If the location corresponds to an existing point, just update its state. + if (Pos->Loc == Loc) { + setDiagnosticMappingInternal(Diag, Map, Pos->State, true); + return; + } + + // Create a new state/point and fit it into the vector of DiagStatePoints + // so that the vector is always ordered according to location. + Pos->Loc.isBeforeInTranslationUnitThan(Loc); + DiagStates.push_back(*Pos->State); + DiagState *NewState = &DiagStates.back(); + setDiagnosticMappingInternal(Diag, Map, NewState, true); + DiagStatePoints.insert(Pos+1, DiagStatePoint(NewState, + FullSourceLoc(Loc, *SourceMgr))); +} + void DiagnosticBuilder::FlushCounts() { DiagObj->NumDiagArgs = NumArgs; DiagObj->NumDiagRanges = NumRanges; diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp index 5d5bf7b72a2..29a8d9270a9 100644 --- a/clang/lib/Basic/DiagnosticIDs.cpp +++ b/clang/lib/Basic/DiagnosticIDs.cpp @@ -282,32 +282,42 @@ const char *DiagnosticIDs::getDescription(unsigned DiagID) const { /// getDiagnosticLevel - Based on the way the client configured the Diagnostic /// object, classify the specified diagnostic ID into a Level, consumable by /// the DiagnosticClient. -DiagnosticIDs::Level DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, - const Diagnostic &Diag) const { +DiagnosticIDs::Level +DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, + const Diagnostic &Diag) const { // Handle custom diagnostics, which cannot be mapped. if (DiagID >= diag::DIAG_UPPER_LIMIT) return CustomDiagInfo->getLevel(DiagID); unsigned DiagClass = getBuiltinDiagClass(DiagID); assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!"); - return getDiagnosticLevel(DiagID, DiagClass, Diag); + return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag); } -/// getDiagnosticLevel - Based on the way the client configured the Diagnostic +/// \brief Based on the way the client configured the Diagnostic /// object, classify the specified diagnostic ID into a Level, consumable by /// the DiagnosticClient. +/// +/// \param Loc The source location we are interested in finding out the +/// diagnostic state. Can be null in order to query the latest state. DiagnosticIDs::Level DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, - const Diagnostic &Diag) const { + SourceLocation Loc, + const Diagnostic &Diag) const { // Specific non-error diagnostics may be mapped to various levels from ignored // to error. Errors can only be mapped to fatal. DiagnosticIDs::Level Result = DiagnosticIDs::Fatal; + Diagnostic::DiagStatePointsTy::iterator + Pos = Diag.GetDiagStatePointForLoc(Loc); + Diagnostic::DiagState *State = Pos->State; + // Get the mapping information, if unset, compute it lazily. - unsigned MappingInfo = Diag.getDiagnosticMappingInfo((diag::kind)DiagID); + unsigned MappingInfo = Diag.getDiagnosticMappingInfo((diag::kind)DiagID, + State); if (MappingInfo == 0) { MappingInfo = GetDefaultDiagMapping(DiagID); - Diag.setDiagnosticMappingInternal(DiagID, MappingInfo, false); + Diag.setDiagnosticMappingInternal(DiagID, MappingInfo, State, false); } switch (MappingInfo & 7) { @@ -404,17 +414,17 @@ static bool WarningOptionCompare(const WarningOption &LHS, } static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping, - Diagnostic &Diag) { + SourceLocation Loc, Diagnostic &Diag) { // Option exists, poke all the members of its diagnostic set. if (const short *Member = Group->Members) { for (; *Member != -1; ++Member) - Diag.setDiagnosticMapping(*Member, Mapping); + Diag.setDiagnosticMapping(*Member, Mapping, Loc); } // Enable/disable all subgroups along with this one. if (const short *SubGroups = Group->SubGroups) { for (; *SubGroups != (short)-1; ++SubGroups) - MapGroupMembers(&OptionTable[(short)*SubGroups], Mapping, Diag); + MapGroupMembers(&OptionTable[(short)*SubGroups], Mapping, Loc, Diag); } } @@ -423,7 +433,18 @@ static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping, /// ignores the request if "Group" was unknown, false otherwise. bool DiagnosticIDs::setDiagnosticGroupMapping(const char *Group, diag::Mapping Map, + SourceLocation Loc, Diagnostic &Diag) const { + assert((Loc.isValid() || + Diag.DiagStatePoints.empty() || + Diag.DiagStatePoints.back().Loc.isInvalid()) && + "Loc should be invalid only when the mapping comes from command-line"); + assert((Loc.isInvalid() || Diag.DiagStatePoints.empty() || + Diag.DiagStatePoints.back().Loc.isInvalid() || + !Diag.SourceMgr->isBeforeInTranslationUnit(Loc, + Diag.DiagStatePoints.back().Loc)) && + "Source location of new mapping is before the previous one!"); + WarningOption Key = { Group, 0, 0 }; const WarningOption *Found = std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key, @@ -432,7 +453,7 @@ bool DiagnosticIDs::setDiagnosticGroupMapping(const char *Group, strcmp(Found->Name, Group) != 0) return true; // Option not found. - MapGroupMembers(Found, Map, Diag); + MapGroupMembers(Found, Map, Loc, Diag); return false; } @@ -475,7 +496,8 @@ bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const { // *map* warnings/extensions to errors. ShouldEmitInSystemHeader = DiagClass == CLASS_ERROR; - DiagLevel = getDiagnosticLevel(DiagID, DiagClass, Diag); + DiagLevel = getDiagnosticLevel(DiagID, DiagClass, Info.getLocation(), + Diag); } } diff --git a/clang/lib/Basic/SourceLocation.cpp b/clang/lib/Basic/SourceLocation.cpp index 1571e2205f8..5062d43f58f 100644 --- a/clang/lib/Basic/SourceLocation.cpp +++ b/clang/lib/Basic/SourceLocation.cpp @@ -110,6 +110,11 @@ bool FullSourceLoc::isInSystemHeader() const { return SrcMgr->isInSystemHeader(*this); } +bool FullSourceLoc::isBeforeInTranslationUnitThan(SourceLocation Loc) const { + assert(isValid()); + return SrcMgr->isBeforeInTranslationUnit(*this, Loc); +} + const char *FullSourceLoc::getCharacterData(bool *Invalid) const { assert(isValid()); return SrcMgr->getCharacterData(*this, Invalid); diff --git a/clang/lib/Lex/MacroInfo.cpp b/clang/lib/Lex/MacroInfo.cpp index c6d09349b5e..c819011338e 100644 --- a/clang/lib/Lex/MacroInfo.cpp +++ b/clang/lib/Lex/MacroInfo.cpp @@ -22,8 +22,9 @@ MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) { IsBuiltinMacro = false; IsFromAST = false; IsDisabled = false; - IsUsed = true; + IsUsed = false; IsAllowRedefinitionsWithoutWarning = false; + IsWarnIfUnused = false; ArgumentList = 0; NumArguments = 0; diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 3414c27bfc8..467d4858883 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1504,11 +1504,6 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { } } - // If this is the primary source file, remember that this macro hasn't been - // used yet. - if (isInPrimaryFile()) - MI->setIsUsed(false); - MI->setDefinitionEndLoc(LastTok.getLocation()); // Finally, if this identifier already had a macro defined for it, verify that @@ -1536,6 +1531,16 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { setMacroInfo(MacroNameTok.getIdentifierInfo(), MI); + assert(!MI->isUsed()); + // If we need warning for not using the macro, add its location in the + // warn-because-unused-macro set. If it gets used it will be removed from set. + if (isInPrimaryFile() && // don't warn for include'd macros. + Diags->getDiagnosticLevel(diag::pp_macro_not_used, + MI->getDefinitionLoc()) != Diagnostic::Ignored) { + MI->setIsWarnIfUnused(true); + WarnUnusedMacroLocs.insert(MI->getDefinitionLoc()); + } + // If the callbacks want to know, tell them about the macro definition. if (Callbacks) Callbacks->MacroDefined(MacroNameTok, MI); @@ -1569,6 +1574,9 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) { if (Callbacks) Callbacks->MacroUndefined(MacroNameTok, MI); + if (MI->isWarnIfUnused()) + WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); + // Free macro definition. ReleaseMacroInfo(MI); setMacroInfo(MacroNameTok.getIdentifierInfo(), 0); @@ -1621,7 +1629,7 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, // If there is a macro, process it. if (MI) // Mark it used. - MI->setIsUsed(true); + markMacroAsUsed(MI); // Should we include the stuff contained by this directive? if (!MI == isIfndef) { diff --git a/clang/lib/Lex/PPExpressions.cpp b/clang/lib/Lex/PPExpressions.cpp index 79ed8677da7..1451c5a1ef5 100644 --- a/clang/lib/Lex/PPExpressions.cpp +++ b/clang/lib/Lex/PPExpressions.cpp @@ -112,7 +112,7 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT, // If there is a macro, mark it used. if (Result.Val != 0 && ValueLive) { MacroInfo *Macro = PP.getMacroInfo(II); - Macro->setIsUsed(true); + PP.markMacroAsUsed(Macro); } // Consume identifier. diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp index 4a404059926..eef42b69d87 100644 --- a/clang/lib/Lex/PPLexerChange.cpp +++ b/clang/lib/Lex/PPLexerChange.cpp @@ -250,15 +250,11 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { CurPPLexer = 0; - // This is the end of the top-level file. If the diag::pp_macro_not_used - // diagnostic is enabled, look for macros that have not been used. - if (getDiagnostics().getDiagnosticLevel(diag::pp_macro_not_used) != - Diagnostic::Ignored) { - for (macro_iterator I = macro_begin(false), E = macro_end(false); - I != E; ++I) - if (!I->second->isUsed()) - Diag(I->second->getDefinitionLoc(), diag::pp_macro_not_used); - } + // This is the end of the top-level file. 'WarnUnusedMacroLocs' has collected + // all macro locations that we need to warn because they are not used. + for (WarnUnusedMacroLocsTy::iterator + I=WarnUnusedMacroLocs.begin(), E=WarnUnusedMacroLocs.end(); I!=E; ++I) + Diag(*I, diag::pp_macro_not_used); return true; } diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index d3f3db31daa..333da11143b 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -223,7 +223,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, } // Notice that this macro has been used. - MI->setIsUsed(true); + markMacroAsUsed(MI); // If we started lexing a macro, enter the macro expansion body. @@ -869,3 +869,11 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { } CreateString(OS.str().data(), OS.str().size(), Tok, Tok.getLocation()); } + +void Preprocessor::markMacroAsUsed(MacroInfo *MI) { + // If the 'used' status changed, and the macro requires 'unused' warning, + // remove its SourceLocation from the warn-for-unused-macro locations. + if (MI->isWarnIfUnused() && !MI->isUsed()) + WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); + MI->setIsUsed(true); +} diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index 58625520a99..e6a53a10436 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -646,7 +646,11 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { if (iter != PragmaPushMacroInfo.end()) { // Release the MacroInfo currently associated with IdentInfo. MacroInfo *CurrentMI = getMacroInfo(IdentInfo); - if (CurrentMI) ReleaseMacroInfo(CurrentMI); + if (CurrentMI) { + if (CurrentMI->isWarnIfUnused()) + WarnUnusedMacroLocs.erase(CurrentMI->getDefinitionLoc()); + ReleaseMacroInfo(CurrentMI); + } // Get the MacroInfo we want to reinstall. MacroInfo *MacroToReInstall = iter->second.back(); @@ -810,6 +814,7 @@ public: explicit PragmaDiagnosticHandler() : PragmaHandler("diagnostic") {} virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &DiagToken) { + SourceLocation DiagLoc = DiagToken.getLocation(); Token Tok; PP.LexUnexpandedToken(Tok); if (Tok.isNot(tok::identifier)) { @@ -828,12 +833,12 @@ public: else if (II->isStr("fatal")) Map = diag::MAP_FATAL; else if (II->isStr("pop")) { - if (!PP.getDiagnostics().popMappings()) + if (!PP.getDiagnostics().popMappings(DiagLoc)) PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop); return; } else if (II->isStr("push")) { - PP.getDiagnostics().pushMappings(); + PP.getDiagnostics().pushMappings(DiagLoc); return; } else { PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid); @@ -883,7 +888,7 @@ public: } if (PP.getDiagnostics().setDiagnosticGroupMapping(WarningName.c_str()+2, - Map)) + Map, DiagLoc)) PP.Diag(StrToks[0].getLocation(), diag::warn_pragma_diagnostic_unknown_warning) << WarningName; } diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index a9001c6e769..f4fde40bfba 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -216,9 +216,11 @@ struct CheckFallThroughDiagnostics { unsigned diag_AlwaysFallThrough_ReturnsNonVoid; unsigned diag_NeverFallThroughOrReturn; bool funMode; + SourceLocation FuncLoc; static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) { CheckFallThroughDiagnostics D; + D.FuncLoc = Func->getLocation(); D.diag_MaybeFallThrough_HasNoReturn = diag::warn_falloff_noreturn_function; D.diag_MaybeFallThrough_ReturnsNonVoid = @@ -263,18 +265,22 @@ struct CheckFallThroughDiagnostics { bool checkDiagnostics(Diagnostic &D, bool ReturnsVoid, bool HasNoReturn) const { if (funMode) { - return (D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function) - == Diagnostic::Ignored || ReturnsVoid) - && (D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr) - == Diagnostic::Ignored || !HasNoReturn) - && (D.getDiagnosticLevel(diag::warn_suggest_noreturn_block) - == Diagnostic::Ignored || !ReturnsVoid); + return (ReturnsVoid || + D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function, + FuncLoc) == Diagnostic::Ignored) + && (!HasNoReturn || + D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr, + FuncLoc) == Diagnostic::Ignored) + && (!ReturnsVoid || + D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) + == Diagnostic::Ignored); } // For blocks. return ReturnsVoid && !HasNoReturn - && (D.getDiagnosticLevel(diag::warn_suggest_noreturn_block) - == Diagnostic::Ignored || !ReturnsVoid); + && (!ReturnsVoid || + D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) + == Diagnostic::Ignored); } }; @@ -363,7 +369,8 @@ clang::sema::AnalysisBasedWarnings::Policy::Policy() { clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s) { Diagnostic &D = S.getDiagnostics(); DefaultPolicy.enableCheckUnreachable = (unsigned) - (D.getDiagnosticLevel(diag::warn_unreachable) != Diagnostic::Ignored); + (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) != + Diagnostic::Ignored); } void clang::sema:: diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index b699f5a318c..c75b27c3ecc 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2863,11 +2863,12 @@ void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T) { if (!Suspicious) return; // ...but it's currently ignored... - if (S.Diags.getDiagnosticLevel(diag::warn_impcast_integer_sign_conditional)) + if (S.Diags.getDiagnosticLevel(diag::warn_impcast_integer_sign_conditional, + CC)) return; // ...and -Wsign-compare isn't... - if (!S.Diags.getDiagnosticLevel(diag::warn_mixed_sign_conditional)) + if (!S.Diags.getDiagnosticLevel(diag::warn_mixed_sign_conditional, CC)) return; // ...then check whether it would have warned about either of the @@ -3028,7 +3029,8 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd, void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) { // This is actually a lot of work to potentially be doing on every // cast; don't do it if we're ignoring -Wcast_align (as is the default). - if (getDiagnostics().getDiagnosticLevel(diag::warn_cast_align) + if (getDiagnostics().getDiagnosticLevel(diag::warn_cast_align, + TRange.getBegin()) == Diagnostic::Ignored) return; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 17a1a1badb5..6182e8663b4 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -809,7 +809,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, << Context.BuiltinInfo.GetName(BID) << R; if (Context.BuiltinInfo.getHeaderName(BID) && - Diags.getDiagnosticLevel(diag::ext_implicit_lib_function_decl) + Diags.getDiagnosticLevel(diag::ext_implicit_lib_function_decl, Loc) != Diagnostic::Ignored) Diag(Loc, diag::note_please_include_header) << Context.BuiltinInfo.getHeaderName(BID) @@ -3081,7 +3081,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, /// void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { // Return if warning is ignored. - if (Diags.getDiagnosticLevel(diag::warn_decl_shadow) == Diagnostic::Ignored) + if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, R.getNameLoc()) == + Diagnostic::Ignored) return; // Don't diagnose declarations at file scope. The scope might not @@ -3135,6 +3136,10 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { /// \brief Check -Wshadow without the advantage of a previous lookup. void Sema::CheckShadow(Scope *S, VarDecl *D) { + if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, D->getLocation()) == + Diagnostic::Ignored) + return; + LookupResult R(*this, D->getDeclName(), D->getLocation(), Sema::LookupOrdinaryName, Sema::ForRedeclaration); LookupName(R, S); @@ -5014,10 +5019,6 @@ ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, void Sema::DiagnoseUnusedParameters(ParmVarDecl * const *Param, ParmVarDecl * const *ParamEnd) { - if (Diags.getDiagnosticLevel(diag::warn_unused_parameter) == - Diagnostic::Ignored) - return; - // Don't diagnose unused-parameter errors in template instantiations; we // will already have done so in the template itself. if (!ActiveTemplateInstantiations.empty()) @@ -5048,9 +5049,6 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param, << D->getDeclName() << Size; } - if (Diags.getDiagnosticLevel(diag::warn_parameter_size)==Diagnostic::Ignored) - return; - // Warn if any parameter is pass-by-value and larger than the specified // threshold. for (; Param != ParamEnd; ++Param) { @@ -5255,9 +5253,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { CheckParmsForFunctionDef(FD->param_begin(), FD->param_end(), /*CheckParameterNames=*/true); - bool ShouldCheckShadow = - Diags.getDiagnosticLevel(diag::warn_decl_shadow) != Diagnostic::Ignored; - // Introduce our parameters into the function scope for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) { ParmVarDecl *Param = FD->getParamDecl(p); @@ -5265,8 +5260,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { // If this has an identifier, add it to the scope stack. if (Param->getIdentifier() && FnBodyScope) { - if (ShouldCheckShadow) - CheckShadow(FnBodyScope, Param); + CheckShadow(FnBodyScope, Param); PushOnScopeChains(Param, FnBodyScope); } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index eec80f0d5a4..d5387159170 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1991,8 +1991,19 @@ DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef, if (Constructor->getDeclContext()->isDependentContext()) return; - if (SemaRef.Diags.getDiagnosticLevel(diag::warn_initializer_out_of_order) - == Diagnostic::Ignored) + // Don't check initializers order unless the warning is enabled at the + // location of at least one initializer. + bool ShouldCheckOrder = false; + for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) { + CXXBaseOrMemberInitializer *Init = Inits[InitIndex]; + if (SemaRef.Diags.getDiagnosticLevel(diag::warn_initializer_out_of_order, + Init->getSourceLocation()) + != Diagnostic::Ignored) { + ShouldCheckOrder = true; + break; + } + } + if (!ShouldCheckOrder) return; // Build the list of bases and members in the order that they'll diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index f29a01eb454..38e91465d2c 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -969,7 +969,8 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, IDecl->lookupInstanceMethod(method->getSelector()); if (!MethodInClass || !MethodInClass->isSynthesized()) { unsigned DIAG = diag::warn_unimplemented_protocol_method; - if (Diags.getDiagnosticLevel(DIAG) != Diagnostic::Ignored) { + if (Diags.getDiagnosticLevel(DIAG, ImpLoc) + != Diagnostic::Ignored) { WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG); Diag(method->getLocation(), diag::note_method_declared_at); Diag(CDecl->getLocation(), diag::note_required_for_protocol_at) @@ -987,7 +988,7 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, !ClsMap.count(method->getSelector()) && (!Super || !Super->lookupClassMethod(method->getSelector()))) { unsigned DIAG = diag::warn_unimplemented_protocol_method; - if (Diags.getDiagnosticLevel(DIAG) != Diagnostic::Ignored) { + if (Diags.getDiagnosticLevel(DIAG, ImpLoc) != Diagnostic::Ignored) { WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG); Diag(method->getLocation(), diag::note_method_declared_at); Diag(IDecl->getLocation(), diag::note_required_for_protocol_at) << @@ -1325,7 +1326,8 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; bool strictSelectorMatch = receiverIdOrClass && warn && - (Diags.getDiagnosticLevel(diag::warn_strict_multiple_method_decl) != + (Diags.getDiagnosticLevel(diag::warn_strict_multiple_method_decl, + R.getBegin()) != Diagnostic::Ignored); if (warn && MethList.Method && MethList.Next) { bool issueWarning = false; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0d4eb776980..dff9b458ba3 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -8336,17 +8336,13 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { if (Params.empty()) return; - bool ShouldCheckShadow = - Diags.getDiagnosticLevel(diag::warn_decl_shadow) != Diagnostic::Ignored; - for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(), E = CurBlock->TheDecl->param_end(); AI != E; ++AI) { (*AI)->setOwningFunction(CurBlock->TheDecl); // If this has an identifier, add it to the scope stack. if ((*AI)->getIdentifier()) { - if (ShouldCheckShadow) - CheckShadow(CurBlock->TheScope, *AI); + CheckShadow(CurBlock->TheScope, *AI); PushOnScopeChains(*AI, CurBlock->TheScope); } @@ -8670,7 +8666,8 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){ E->getSourceRange(); if (EvalResult.Diag && - Diags.getDiagnosticLevel(diag::ext_expr_not_ice) != Diagnostic::Ignored) + Diags.getDiagnosticLevel(diag::ext_expr_not_ice, EvalResult.DiagLoc) + != Diagnostic::Ignored) Diag(EvalResult.DiagLoc, EvalResult.Diag); if (Result) diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 098f71a529a..bbabf80486e 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2670,7 +2670,8 @@ void ASTReader::ReadUserDiagnosticMappings(Diagnostic &Diag) { while (Idx < UserDiagMappings.size()) { unsigned DiagID = UserDiagMappings[Idx++]; unsigned Map = UserDiagMappings[Idx++]; - Diag.setDiagnosticMappingInternal(DiagID, Map, /*isUser=*/true); + Diag.setDiagnosticMappingInternal(DiagID, Map, Diag.GetCurDiagState(), + /*isUser=*/true); } } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 7b405e9c8b3..26a54b1d55e 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1460,7 +1460,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP) { void ASTWriter::WriteUserDiagnosticMappings(const Diagnostic &Diag) { RecordData Record; for (unsigned i = 0; i != diag::DIAG_UPPER_LIMIT; ++i) { - diag::Mapping Map = Diag.getDiagnosticMappingInfo(i); + diag::Mapping Map = Diag.getDiagnosticMappingInfo(i,Diag.GetCurDiagState()); if (Map & 0x8) { // user mapping. Record.push_back(i); Record.push_back(Map & 0x7); |