Skip to content

Commit

Permalink
Added a flag to the parser to skip method bodies.
Browse files Browse the repository at this point in the history
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154584 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
erikjv committed Apr 12, 2012
1 parent f33d549 commit 6a91d38
Show file tree
Hide file tree
Showing 15 changed files with 106 additions and 34 deletions.
11 changes: 10 additions & 1 deletion include/clang-c/Index.h
Original file line number Diff line number Diff line change
Expand Up @@ -1069,7 +1069,16 @@ enum CXTranslationUnit_Flags {
* Note: this is a *temporary* option that is available only while
* we are testing C++ precompiled preamble support. It is deprecated.
*/
CXTranslationUnit_CXXChainedPCH = 0x20
CXTranslationUnit_CXXChainedPCH = 0x20,

/**
* \brief Used to indicate that function/method bodies should be skipped while
* parsing.
*
* This option can be used to search for declarations/definitions while
* ignoring the usages.
*/
CXTranslationUnit_SkipFunctionBodies = 0x40
};

/**
Expand Down
1 change: 1 addition & 0 deletions include/clang/Frontend/ASTUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,7 @@ class ASTUnit : public ModuleLoader {
TranslationUnitKind TUKind = TU_Complete,
bool CacheCodeCompletionResults = false,
bool AllowPCHWithCompilerErrors = false,
bool SkipFunctionBodies = false,
OwningPtr<ASTUnit> *ErrAST = 0);

/// \brief Reparse the source files using the same command-line options that
Expand Down
5 changes: 5 additions & 0 deletions include/clang/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ class FrontendOptions {
unsigned FixToTemporaries : 1; ///< Apply fixes to temporary files.
unsigned ARCMTMigrateEmitARCErrors : 1; /// Emit ARC errors even if the
/// migrator can fix them
unsigned SkipFunctionBodies : 1; ///< Skip over function bodies to
/// speed up parsing in cases you do
/// not need them (e.g. with code
/// completion).

enum {
ARCMT_None,
Expand Down Expand Up @@ -188,6 +192,7 @@ class FrontendOptions {
ShowVersion = 0;
ARCMTAction = ARCMT_None;
ARCMTMigrateEmitARCErrors = 0;
SkipFunctionBodies = 0;
ObjCMTAction = ObjCMT_None;
}

Expand Down
6 changes: 4 additions & 2 deletions include/clang/Parse/ParseAST.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ namespace clang {
void ParseAST(Preprocessor &pp, ASTConsumer *C,
ASTContext &Ctx, bool PrintStats = false,
TranslationUnitKind TUKind = TU_Complete,
CodeCompleteConsumer *CompletionConsumer = 0);
CodeCompleteConsumer *CompletionConsumer = 0,
bool SkipFunctionBodies = false);

/// \brief Parse the main file known to the preprocessor, producing an
/// abstract syntax tree.
void ParseAST(Sema &S, bool PrintStats = false);
void ParseAST(Sema &S, bool PrintStats = false,
bool SkipFunctionBodies = false);

} // end namespace clang

Expand Down
6 changes: 4 additions & 2 deletions include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,10 @@ class Parser : public CodeCompletionHandler {

IdentifierInfo *getSEHExceptKeyword();

bool SkipFunctionBodies;

public:
Parser(Preprocessor &PP, Sema &Actions);
Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies);
~Parser();

const LangOptions &getLangOpts() const { return PP.getLangOpts(); }
Expand Down Expand Up @@ -1671,7 +1673,7 @@ class Parser : public CodeCompletionHandler {
/// unless the body contains the code-completion point.
///
/// \returns true if the function body was skipped.
bool trySkippingFunctionBodyForCodeCompletion();
bool trySkippingFunctionBody();

bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
const ParsedTemplateInfo &TemplateInfo,
Expand Down
5 changes: 5 additions & 0 deletions lib/Frontend/ASTUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1882,6 +1882,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
TranslationUnitKind TUKind,
bool CacheCodeCompletionResults,
bool AllowPCHWithCompilerErrors,
bool SkipFunctionBodies,
OwningPtr<ASTUnit> *ErrAST) {
if (!Diags.getPtr()) {
// No diagnostics engine was provided, so create our own diagnostics object
Expand Down Expand Up @@ -1925,6 +1926,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
// Override the resources path.
CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;

CI->getFrontendOpts().SkipFunctionBodies = SkipFunctionBodies;

// Create the AST unit.
OwningPtr<ASTUnit> AST;
AST.reset(new ASTUnit(false));
Expand Down Expand Up @@ -2365,6 +2368,8 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
FrontendOpts.ShowGlobalSymbolsInCodeCompletion);
Clang->setCodeCompletionConsumer(AugmentedConsumer);

Clang->getFrontendOpts().SkipFunctionBodies = true;

// If we have a precompiled preamble, try to use it. We only allow
// the use of the precompiled preamble if we're if the completion
// point is within the main file, after the end of the precompiled
Expand Down
1 change: 1 addition & 0 deletions lib/Frontend/CompilerInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ void CompilerInstance::setASTConsumer(ASTConsumer *Value) {

void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
CompletionConsumer.reset(Value);
getFrontendOpts().SkipFunctionBodies = true;
}

// Diagnostics
Expand Down
3 changes: 2 additions & 1 deletion lib/Frontend/FrontendAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,8 @@ void ASTFrontendAction::ExecuteAction() {
if (!CI.hasSema())
CI.createSema(getTranslationUnitKind(), CompletionConsumer);

ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats);
ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats,
CI.getFrontendOpts().SkipFunctionBodies);
}

void PluginASTAction::anchor() { }
Expand Down
14 changes: 8 additions & 6 deletions lib/Parse/ParseAST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,20 @@ using namespace clang;
void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
ASTContext &Ctx, bool PrintStats,
TranslationUnitKind TUKind,
CodeCompleteConsumer *CompletionConsumer) {
CodeCompleteConsumer *CompletionConsumer,
bool SkipFunctionBodies) {

OwningPtr<Sema> S(new Sema(PP, Ctx, *Consumer,
TUKind,
CompletionConsumer));

// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleaupSema(S.get());
llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get());

ParseAST(*S.get(), PrintStats);
ParseAST(*S.get(), PrintStats, SkipFunctionBodies);
}

void clang::ParseAST(Sema &S, bool PrintStats) {
void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
// Collect global stats on Decls/Stmts (until we have a module streamer).
if (PrintStats) {
Decl::EnableStatistics();
Expand All @@ -63,14 +64,15 @@ void clang::ParseAST(Sema &S, bool PrintStats) {

ASTConsumer *Consumer = &S.getASTConsumer();

OwningPtr<Parser> ParseOP(new Parser(S.getPreprocessor(), S));
OwningPtr<Parser> ParseOP(new Parser(S.getPreprocessor(), S,
SkipFunctionBodies));
Parser &P = *ParseOP.get();

PrettyStackTraceParserEntry CrashInfo(P);

// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<Parser>
CleaupParser(ParseOP.get());
CleanupParser(ParseOP.get());

S.getPreprocessor().EnterMainSourceFile();
P.Initialize();
Expand Down
8 changes: 3 additions & 5 deletions lib/Parse/ParseObjc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2811,11 +2811,9 @@ Decl *Parser::ParseLexedObjCMethodDefs(LexedMethod &LM) {
// specified Declarator for the method.
Actions.ActOnStartOfObjCMethodDef(getCurScope(), MDecl);

if (PP.isCodeCompletionEnabled()) {
if (trySkippingFunctionBodyForCodeCompletion()) {
BodyScope.Exit();
return Actions.ActOnFinishFunctionBody(MDecl, 0);
}
if (SkipFunctionBodies && trySkippingFunctionBody()) {
BodyScope.Exit();
return Actions.ActOnFinishFunctionBody(MDecl, 0);
}

StmtResult FnBody(ParseCompoundStatementBody());
Expand Down
24 changes: 10 additions & 14 deletions lib/Parse/ParseStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1958,11 +1958,9 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
assert(Tok.is(tok::l_brace));
SourceLocation LBraceLoc = Tok.getLocation();

if (PP.isCodeCompletionEnabled()) {
if (trySkippingFunctionBodyForCodeCompletion()) {
BodyScope.Exit();
return Actions.ActOnFinishFunctionBody(Decl, 0);
}
if (SkipFunctionBodies && trySkippingFunctionBody()) {
BodyScope.Exit();
return Actions.ActOnFinishFunctionBody(Decl, 0);
}

PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc,
Expand Down Expand Up @@ -2002,11 +2000,9 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) {
else
Actions.ActOnDefaultCtorInitializers(Decl);

if (PP.isCodeCompletionEnabled()) {
if (trySkippingFunctionBodyForCodeCompletion()) {
BodyScope.Exit();
return Actions.ActOnFinishFunctionBody(Decl, 0);
}
if (SkipFunctionBodies && trySkippingFunctionBody()) {
BodyScope.Exit();
return Actions.ActOnFinishFunctionBody(Decl, 0);
}

SourceLocation LBraceLoc = Tok.getLocation();
Expand All @@ -2023,17 +2019,17 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) {
return Actions.ActOnFinishFunctionBody(Decl, FnBody.take());
}

bool Parser::trySkippingFunctionBodyForCodeCompletion() {
bool Parser::trySkippingFunctionBody() {
assert(Tok.is(tok::l_brace));
assert(PP.isCodeCompletionEnabled() &&
"Should only be called when in code-completion mode");
assert(SkipFunctionBodies &&
"Should only be called when SkipFunctionBodies is enabled");

// We're in code-completion mode. Skip parsing for all function bodies unless
// the body contains the code-completion point.
TentativeParsingAction PA(*this);
ConsumeBrace();
if (SkipUntil(tok::r_brace, /*StopAtSemi=*/false, /*DontConsume=*/false,
/*StopAtCodeCompletion=*/true)) {
/*StopAtCodeCompletion=*/PP.isCodeCompletionEnabled())) {
PA.Commit();
return true;
}
Expand Down
5 changes: 3 additions & 2 deletions lib/Parse/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ IdentifierInfo *Parser::getSEHExceptKeyword() {
return Ident__except;
}

Parser::Parser(Preprocessor &pp, Sema &actions)
Parser::Parser(Preprocessor &pp, Sema &actions, bool SkipFunctionBodies)
: PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
GreaterThanIsOperator(true), ColonIsSacred(false),
InMessageExpression(false), TemplateParameterDepth(0) {
InMessageExpression(false), TemplateParameterDepth(0),
SkipFunctionBodies(SkipFunctionBodies) {
Tok.setKind(tok::eof);
Actions.CurScope = 0;
NumCachedScopes = 0;
Expand Down
45 changes: 45 additions & 0 deletions test/Parser/skip-function-bodies.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// RUN: env CINDEXTEST_SKIP_FUNCTION_BODIES=1 c-index-test -test-load-source all %s | FileCheck %s

class A {
class B {};

public:
A() {
struct C {
void d() {}
};
}

typedef B E;
};

@interface F
- (void) G;
@end
@implementation F
- (void) G {
typedef A H;
class I {};
}
@end

void J() {
class K {};
}

// CHECK: skip-function-bodies.mm:3:7: ClassDecl=A:3:7 (Definition) Extent=[3:1 - 14:2]
// CHECK: skip-function-bodies.mm:4:9: ClassDecl=B:4:9 (Definition) Extent=[4:3 - 4:13]
// CHECK: skip-function-bodies.mm:6:1: CXXAccessSpecifier=:6:1 (Definition) Extent=[6:1 - 6:8]
// CHECK: skip-function-bodies.mm:7:3: CXXConstructor=A:7:3 Extent=[7:3 - 7:6]
// CHECK-NOT: skip-function-bodies.mm:8:12: StructDecl=C:8:12 (Definition) Extent=[8:5 - 10:6]
// CHECK-NOT: skip-function-bodies.mm:9:12: CXXMethod=d:9:12 (Definition) Extent=[9:7 - 9:18]
// CHECK: skip-function-bodies.mm:13:13: TypedefDecl=E:13:13 (Definition) Extent=[13:3 - 13:14]
// CHECK: skip-function-bodies.mm:13:11: TypeRef=class A::B:4:9 Extent=[13:11 - 13:12]
// CHECK: skip-function-bodies.mm:16:12: ObjCInterfaceDecl=F:16:12 Extent=[16:1 - 18:5]
// CHECK: skip-function-bodies.mm:17:10: ObjCInstanceMethodDecl=G:17:10 Extent=[17:1 - 17:12]
// CHECK: skip-function-bodies.mm:19:17: ObjCImplementationDecl=F:19:17 (Definition) Extent=[19:1 - 24:2]
// CHECK: skip-function-bodies.mm:20:10: ObjCInstanceMethodDecl=G:20:10 Extent=[20:1 - 20:13]
// CHECK-NOT: skip-function-bodies.mm:21:13: TypedefDecl=H:21:13 (Definition) Extent=[21:3 - 21:14]
// CHECK-NOT: skip-function-bodies.mm:21:11: TypeRef=class A:3:7 Extent=[21:11 - 21:12]
// CHECK: skip-function-bodies.mm:26:6: FunctionDecl=J:26:6 Extent=[26:1 - 26:9]
// CHECK-NOT: skip-function-bodies.mm:27:9: ClassDecl=K:27:9 (Definition) Extent=[27:3 - 27:13]
2 changes: 2 additions & 0 deletions tools/c-index-test/c-index-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ static unsigned getDefaultParsingOptions() {
options |= CXTranslationUnit_CacheCompletionResults;
if (getenv("CINDEXTEST_COMPLETION_NO_CACHING"))
options &= ~CXTranslationUnit_CacheCompletionResults;
if (getenv("CINDEXTEST_SKIP_FUNCTION_BODIES"))
options |= CXTranslationUnit_SkipFunctionBodies;

return options;
}
Expand Down
4 changes: 3 additions & 1 deletion tools/libclang/CIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2521,7 +2521,8 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
= (options & CXTranslationUnit_Incomplete)? TU_Prefix : TU_Complete;
bool CacheCodeCompetionResults
= options & CXTranslationUnit_CacheCompletionResults;

bool SkipFunctionBodies = options & CXTranslationUnit_SkipFunctionBodies;

// Configure the diagnostics.
DiagnosticOptions DiagOpts;
IntrusiveRefCntPtr<DiagnosticsEngine>
Expand Down Expand Up @@ -2605,6 +2606,7 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
TUKind,
CacheCodeCompetionResults,
/*AllowPCHWithCompilerErrors=*/true,
SkipFunctionBodies,
&ErrUnit));

if (NumErrors != Diags->getClient()->getNumErrors()) {
Expand Down

0 comments on commit 6a91d38

Please sign in to comment.