diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 8 | ||||
-rw-r--r-- | lib/AST/CommentSema.cpp | 24 | ||||
-rw-r--r-- | lib/AST/RawCommentList.cpp | 4 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 33 | ||||
-rw-r--r-- | lib/Sema/AnalysisBasedWarnings.cpp | 66 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 2 |
6 files changed, 71 insertions, 66 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index f19a2aaaf7..83f3f9ca11 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -355,7 +355,9 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl( return RC; } -comments::FullComment *ASTContext::getCommentForDecl(const Decl *D) const { +comments::FullComment *ASTContext::getCommentForDecl( + const Decl *D, + const Preprocessor *PP) const { D = adjustDeclToTemplate(D); const Decl *Canonical = D->getCanonicalDecl(); llvm::DenseMap<const Decl *, comments::FullComment *>::iterator Pos = @@ -373,9 +375,9 @@ comments::FullComment *ASTContext::getCommentForDecl(const Decl *D) const { // because comments can contain references to parameter names which can be // different across redeclarations. if (D != OriginalDecl) - return getCommentForDecl(OriginalDecl); + return getCommentForDecl(OriginalDecl, PP); - comments::FullComment *FC = RC->parse(*this, D); + comments::FullComment *FC = RC->parse(*this, PP, D); ParsedComments[Canonical] = FC; return FC; } diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp index 4f9f1f241c..dd746ad119 100644 --- a/lib/AST/CommentSema.cpp +++ b/lib/AST/CommentSema.cpp @@ -13,7 +13,9 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/SourceManager.h" +#include "clang/Lex/Preprocessor.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/SmallString.h" namespace clang { namespace comments { @@ -23,9 +25,10 @@ namespace { } // unnamed namespace Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, - DiagnosticsEngine &Diags, CommandTraits &Traits) : + DiagnosticsEngine &Diags, CommandTraits &Traits, + const Preprocessor *PP) : Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits), - ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL) { + PP(PP), ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL) { } void Sema::setDecl(const Decl *D) { @@ -527,10 +530,25 @@ void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) { FD->doesThisDeclarationHaveABody()) return; + StringRef AttributeSpelling = "__attribute__((deprecated))"; + if (PP) { + TokenValue Tokens[] = { + tok::kw___attribute, tok::l_paren, tok::l_paren, + PP->getIdentifierInfo("deprecated"), + tok::r_paren, tok::r_paren + }; + StringRef MacroName = PP->getLastMacroWithSpelling(FD->getLocation(), + Tokens); + if (!MacroName.empty()) + AttributeSpelling = MacroName; + } + + SmallString<64> TextToInsert(" "); + TextToInsert += AttributeSpelling; Diag(FD->getLocEnd(), diag::note_add_deprecation_attr) << FixItHint::CreateInsertion(FD->getLocEnd().getLocWithOffset(1), - " __attribute__((deprecated))"); + TextToInsert); } } diff --git a/lib/AST/RawCommentList.cpp b/lib/AST/RawCommentList.cpp index 28ef6112b8..80b627293e 100644 --- a/lib/AST/RawCommentList.cpp +++ b/lib/AST/RawCommentList.cpp @@ -159,6 +159,7 @@ const char *RawComment::extractBriefText(const ASTContext &Context) const { } comments::FullComment *RawComment::parse(const ASTContext &Context, + const Preprocessor *PP, const Decl *D) const { // Make sure that RawText is valid. getRawText(Context.getSourceManager()); @@ -168,7 +169,8 @@ comments::FullComment *RawComment::parse(const ASTContext &Context, RawText.begin(), RawText.end()); comments::Sema S(Context.getAllocator(), Context.getSourceManager(), Context.getDiagnostics(), - Context.getCommentCommandTraits()); + Context.getCommentCommandTraits(), + PP); S.setDecl(D); comments::Parser P(L, S, Context.getAllocator(), Context.getSourceManager(), Context.getDiagnostics(), diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 872cda390a..a0fc265b6b 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -285,6 +285,39 @@ Preprocessor::macro_end(bool IncludeExternalMacros) const { return Macros.end(); } +/// \brief Compares macro tokens with a specified token value sequence. +static bool MacroDefinitionEquals(const MacroInfo *MI, + llvm::ArrayRef<TokenValue> Tokens) { + return Tokens.size() == MI->getNumTokens() && + std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin()); +} + +StringRef Preprocessor::getLastMacroWithSpelling( + SourceLocation Loc, + ArrayRef<TokenValue> Tokens) const { + SourceLocation BestLocation; + StringRef BestSpelling; + for (Preprocessor::macro_iterator I = macro_begin(), E = macro_end(); + I != E; ++I) { + if (!I->second->isObjectLike()) + continue; + const MacroInfo *MI = I->second->findDefinitionAtLoc(Loc, SourceMgr); + if (!MI) + continue; + if (!MacroDefinitionEquals(MI, Tokens)) + continue; + SourceLocation Location = I->second->getDefinitionLoc(); + // Choose the macro defined latest. + if (BestLocation.isInvalid() || + (Location.isValid() && + SourceMgr.isBeforeInTranslationUnit(BestLocation, Location))) { + BestLocation = Location; + BestSpelling = I->first->getName(); + } + } + return BestSpelling; +} + void Preprocessor::recomputeCurLexerKind() { if (CurLexer) CurLexerKind = CLK_Lexer; diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index ad5c739037..67d290b73c 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -41,6 +41,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" @@ -679,61 +680,6 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, return true; } -/// \brief Stores token information for comparing actual tokens with -/// predefined values. Only handles simple tokens and identifiers. -class TokenValue { - tok::TokenKind Kind; - IdentifierInfo *II; - -public: - TokenValue(tok::TokenKind Kind) : Kind(Kind), II(0) { - assert(Kind != tok::raw_identifier && "Raw identifiers are not supported."); - assert(Kind != tok::identifier && - "Identifiers should be created by TokenValue(IdentifierInfo *)"); - assert(!tok::isLiteral(Kind) && "Literals are not supported."); - assert(!tok::isAnnotation(Kind) && "Annotations are not supported."); - } - TokenValue(IdentifierInfo *II) : Kind(tok::identifier), II(II) {} - bool operator==(const Token &Tok) const { - return Tok.getKind() == Kind && - (!II || II == Tok.getIdentifierInfo()); - } -}; - -/// \brief Compares macro tokens with a specified token value sequence. -static bool MacroDefinitionEquals(const MacroInfo *MI, - llvm::ArrayRef<TokenValue> Tokens) { - return Tokens.size() == MI->getNumTokens() && - std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin()); -} - -static std::string GetSuitableSpelling(Preprocessor &PP, SourceLocation L, - llvm::ArrayRef<TokenValue> Tokens, - const char *Spelling) { - SourceManager &SM = PP.getSourceManager(); - SourceLocation BestLocation; - std::string BestSpelling = Spelling; - for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); - I != E; ++I) { - if (!I->second->isObjectLike()) - continue; - const MacroInfo *MI = I->second->findDefinitionAtLoc(L, SM); - if (!MI) - continue; - if (!MacroDefinitionEquals(MI, Tokens)) - continue; - SourceLocation Location = I->second->getDefinitionLoc(); - // Choose the macro defined latest. - if (BestLocation.isInvalid() || - (Location.isValid() && - SM.isBeforeInTranslationUnit(BestLocation, Location))) { - BestLocation = Location; - BestSpelling = I->first->getName(); - } - } - return BestSpelling; -} - namespace { class FallthroughMapper : public RecursiveASTVisitor<FallthroughMapper> { public: @@ -914,11 +860,15 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, tok::coloncolon, PP.getIdentifierInfo("fallthrough"), tok::r_square, tok::r_square }; - std::string AnnotationSpelling = GetSuitableSpelling( - PP, L, Tokens, "[[clang::fallthrough]]"); + StringRef AnnotationSpelling = "[[clang::fallthrough]]"; + StringRef MacroName = PP.getLastMacroWithSpelling(L, Tokens); + if (!MacroName.empty()) + AnnotationSpelling = MacroName; + SmallString<64> TextToInsert(AnnotationSpelling); + TextToInsert += "; "; S.Diag(L, diag::note_insert_fallthrough_fixit) << AnnotationSpelling << - FixItHint::CreateInsertion(L, AnnotationSpelling + "; "); + FixItHint::CreateInsertion(L, TextToInsert); } } S.Diag(L, diag::note_insert_break_fixit) << diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 592956b9db..019a7f141a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -7266,7 +7266,7 @@ void Sema::ActOnDocumentableDecls(Decl **Group, unsigned NumDecls) { // the lookahead in the lexer: we've consumed the semicolon and looked // ahead through comments. for (unsigned i = 0; i != NumDecls; ++i) - Context.getCommentForDecl(Group[i]); + Context.getCommentForDecl(Group[i], &PP); } } |