aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Frontend/FrontendAction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Frontend/FrontendAction.cpp')
-rw-r--r--clang/lib/Frontend/FrontendAction.cpp129
1 files changed, 93 insertions, 36 deletions
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 1d82fc7..2d69f8c 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -9,6 +9,7 @@
#include "clang/Frontend/FrontendAction.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticOptions.h"
@@ -39,6 +40,7 @@
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/ErrorHandling.h"
@@ -87,12 +89,25 @@ public:
// reducing the granularity and making the output less useful.
return;
}
- if (auto *DC = D->getDeclContext(); !DC || !DC->isFileContext()) {
+ auto *DC = D->getLexicalDeclContext();
+ if (!DC || !DC->isFileContext()) {
// We choose to work at namespace level to reduce complexity and the
// number of cases we care about.
return;
}
+
PendingDecls.push_back(D);
+ if (auto *NS = dyn_cast<NamespaceDecl>(DC)) {
+ // Add any namespaces we have not seen before.
+ // Note that we filter out namespaces from DeclRead as it includes too
+ // all redeclarations and we only want the ones that had other used
+ // declarations.
+ while (NS && ProcessedNamespaces.insert(NS).second) {
+ PendingDecls.push_back(NS);
+
+ NS = dyn_cast<NamespaceDecl>(NS->getLexicalParent());
+ }
+ }
}
struct Position {
@@ -141,23 +156,25 @@ public:
OptionalFileEntryRef Ref;
};
llvm::DenseMap<const FileEntry *, FileData> FileToRanges;
+
for (const Decl *D : PendingDecls) {
- CharSourceRange R = SM.getExpansionRange(D->getSourceRange());
- if (!R.isValid())
- continue;
+ for (CharSourceRange R : getRangesToMark(D)) {
+ if (!R.isValid())
+ continue;
- auto *F = SM.getFileEntryForID(SM.getFileID(R.getBegin()));
- if (F != SM.getFileEntryForID(SM.getFileID(R.getEnd()))) {
- // Such cases are rare and difficult to handle.
- continue;
- }
+ auto *F = SM.getFileEntryForID(SM.getFileID(R.getBegin()));
+ if (F != SM.getFileEntryForID(SM.getFileID(R.getEnd()))) {
+ // Such cases are rare and difficult to handle.
+ continue;
+ }
- auto &Data = FileToRanges[F];
- if (!Data.Ref)
- Data.Ref = SM.getFileEntryRefForID(SM.getFileID(R.getBegin()));
- Data.FromTo.push_back(
- {Position::GetBeginSpelling(SM, R),
- Position::GetEndSpelling(SM, R, D->getLangOpts())});
+ auto &Data = FileToRanges[F];
+ if (!Data.Ref)
+ Data.Ref = SM.getFileEntryRefForID(SM.getFileID(R.getBegin()));
+ Data.FromTo.push_back(
+ {Position::GetBeginSpelling(SM, R),
+ Position::GetEndSpelling(SM, R, D->getLangOpts())});
+ }
}
// To simplify output, merge consecutive and intersecting ranges.
@@ -188,10 +205,49 @@ public:
private:
std::vector<const Decl *> PendingDecls;
+ llvm::SmallPtrSet<const NamespaceDecl *, 0> ProcessedNamespaces;
bool IsCollectingDecls = true;
const SourceManager &SM;
std::unique_ptr<llvm::raw_ostream> OS;
+ llvm::SmallVector<CharSourceRange, 2> getRangesToMark(const Decl *D) {
+ auto *NS = dyn_cast<NamespaceDecl>(D);
+ if (!NS)
+ return {SM.getExpansionRange(D->getSourceRange())};
+
+ SourceLocation LBraceLoc;
+ if (NS->isAnonymousNamespace()) {
+ LBraceLoc = NS->getLocation();
+ } else {
+ // Start with the location of the identifier.
+ SourceLocation TokenBeforeLBrace = NS->getLocation();
+ if (NS->hasAttrs()) {
+ for (auto *A : NS->getAttrs()) {
+ // But attributes may go after it.
+ if (SM.isBeforeInTranslationUnit(TokenBeforeLBrace,
+ A->getRange().getEnd())) {
+ // Give up, the attributes are often coming from macros and we
+ // cannot skip them reliably.
+ return {};
+ }
+ }
+ }
+ auto &LangOpts = D->getLangOpts();
+ // Now skip one token, the next should be the lbrace.
+ Token Tok;
+ if (Lexer::getRawToken(TokenBeforeLBrace, Tok, SM, LangOpts, true) ||
+ Lexer::getRawToken(Tok.getEndLoc(), Tok, SM, LangOpts, true) ||
+ Tok.getKind() != tok::l_brace) {
+ // On error or if we did not find the token we expected, avoid marking
+ // everything inside the namespace as used.
+ return {};
+ }
+ LBraceLoc = Tok.getLocation();
+ }
+ return {SM.getExpansionRange(SourceRange(NS->getBeginLoc(), LBraceLoc)),
+ SM.getExpansionRange(NS->getRBraceLoc())};
+ }
+
void printJson(llvm::ArrayRef<RequiredRanges> Result) {
*OS << "{\n";
*OS << R"( "required_ranges": [)" << "\n";
@@ -226,6 +282,8 @@ private:
}
*OS << " ]\n";
*OS << "}\n";
+
+ OS->flush();
}
};
@@ -763,11 +821,11 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// If we're replaying the build of an AST file, import it and set up
// the initial state from its build.
if (ReplayASTFile) {
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags = CI.getDiagnosticsPtr();
// The AST unit populates its own diagnostics engine rather than ours.
- IntrusiveRefCntPtr<DiagnosticsEngine> ASTDiags(new DiagnosticsEngine(
- Diags->getDiagnosticIDs(), Diags->getDiagnosticOptions()));
+ auto ASTDiags = llvm::makeIntrusiveRefCnt<DiagnosticsEngine>(
+ Diags->getDiagnosticIDs(), Diags->getDiagnosticOptions());
ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false);
// FIXME: What if the input is a memory buffer?
@@ -787,7 +845,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// Set the shared objects, these are reset when we finish processing the
// file, otherwise the CompilerInstance will happily destroy them.
- CI.setFileManager(&AST->getFileManager());
+ CI.setFileManager(AST->getFileManagerPtr());
CI.createSourceManager(CI.getFileManager());
CI.getSourceManager().initializeForReplay(AST->getSourceManager());
@@ -835,7 +893,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
assert(hasASTFileSupport() &&
"This action does not have AST file support!");
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags = CI.getDiagnosticsPtr();
// FIXME: What if the input is a memory buffer?
StringRef InputFile = Input.getFile();
@@ -854,13 +912,13 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// Set the shared objects, these are reset when we finish processing the
// file, otherwise the CompilerInstance will happily destroy them.
- CI.setFileManager(&AST->getFileManager());
- CI.setSourceManager(&AST->getSourceManager());
+ CI.setFileManager(AST->getFileManagerPtr());
+ CI.setSourceManager(AST->getSourceManagerPtr());
CI.setPreprocessor(AST->getPreprocessorPtr());
Preprocessor &PP = CI.getPreprocessor();
PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),
PP.getLangOpts());
- CI.setASTContext(&AST->getASTContext());
+ CI.setASTContext(AST->getASTContextPtr());
setCurrentInput(Input, std::move(AST));
@@ -1114,11 +1172,12 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) {
// Convert headers to PCH and chain them.
- IntrusiveRefCntPtr<ExternalSemaSource> source, FinalReader;
+ IntrusiveRefCntPtr<ExternalSemaSource> source;
+ IntrusiveRefCntPtr<ASTReader> FinalReader;
source = createChainedIncludesSource(CI, FinalReader);
if (!source)
return false;
- CI.setASTReader(static_cast<ASTReader *>(FinalReader.get()));
+ CI.setASTReader(FinalReader);
CI.getASTContext().setExternalSource(source);
} else if (CI.getLangOpts().Modules ||
!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
@@ -1194,23 +1253,21 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// provides the layouts from that file.
if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() &&
CI.hasASTContext() && !CI.getASTContext().getExternalSource()) {
- IntrusiveRefCntPtr<ExternalASTSource>
- Override(new LayoutOverrideSource(
- CI.getFrontendOpts().OverrideRecordLayoutsFile));
+ auto Override = llvm::makeIntrusiveRefCnt<LayoutOverrideSource>(
+ CI.getFrontendOpts().OverrideRecordLayoutsFile);
CI.getASTContext().setExternalSource(Override);
}
// Setup HLSL External Sema Source
if (CI.getLangOpts().HLSL && CI.hasASTContext()) {
- IntrusiveRefCntPtr<ExternalSemaSource> HLSLSema(
- new HLSLExternalSemaSource());
- if (auto *SemaSource = dyn_cast_if_present<ExternalSemaSource>(
- CI.getASTContext().getExternalSource())) {
- IntrusiveRefCntPtr<ExternalSemaSource> MultiSema(
- new MultiplexExternalSemaSource(SemaSource, HLSLSema.get()));
- CI.getASTContext().setExternalSource(MultiSema);
+ auto HLSLSema = llvm::makeIntrusiveRefCnt<HLSLExternalSemaSource>();
+ if (auto SemaSource = dyn_cast_if_present<ExternalSemaSource>(
+ CI.getASTContext().getExternalSourcePtr())) {
+ auto MultiSema = llvm::makeIntrusiveRefCnt<MultiplexExternalSemaSource>(
+ std::move(SemaSource), std::move(HLSLSema));
+ CI.getASTContext().setExternalSource(std::move(MultiSema));
} else
- CI.getASTContext().setExternalSource(HLSLSema);
+ CI.getASTContext().setExternalSource(std::move(HLSLSema));
}
FailureCleanup.release();