From f807fe0d1a865f4c6ba7e494cf4ae360c4173521 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 14 Apr 2009 16:27:31 +0000 Subject: [PATCH] When building a PCH file, don't perform end-of-translation-unit wrap-up (e.g., turning tentative definitions into definitions). Also, very that, when we actually use the PCH file, we get the ride code generation for tentative definitions and definitions that show up in the PCH file. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69043 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/ParseAST.h | 14 ++++++++++---- lib/Sema/ParseAST.cpp | 5 +++-- lib/Sema/Sema.cpp | 9 +++++++-- lib/Sema/Sema.h | 16 ++++++++++++++-- test/PCH/external-defs.c | 19 ++++++++++++++++--- test/PCH/external-defs.h | 9 ++++++++- tools/clang-cc/clang-cc.cpp | 6 +++++- 7 files changed, 63 insertions(+), 15 deletions(-) diff --git a/include/clang/Sema/ParseAST.h b/include/clang/Sema/ParseAST.h index 882460029d..bdce5e95ef 100644 --- a/include/clang/Sema/ParseAST.h +++ b/include/clang/Sema/ParseAST.h @@ -19,12 +19,18 @@ namespace clang { class ASTConsumer; class ASTContext; - /// ParseAST - Parse the entire file specified, notifying the ASTConsumer as - /// the file is parsed. This inserts the parsed decls into the translation unit - /// held by Ctx. + /// \brief Parse the entire file specified, notifying the ASTConsumer as + /// the file is parsed. /// + /// This operation inserts the parsed decls into the translation + /// unit held by Ctx. + /// + /// \param CompleteTranslationUnit When true, the parsed file is + /// considered to be a complete translation unit, and any + /// end-of-translation-unit wrapup will be performed. void ParseAST(Preprocessor &pp, ASTConsumer *C, - ASTContext &Ctx, bool PrintStats = false); + ASTContext &Ctx, bool PrintStats = false, + bool CompleteTranslationUnit = true); } // end namespace clang diff --git a/lib/Sema/ParseAST.cpp b/lib/Sema/ParseAST.cpp index bb5acb0ee8..d237f7539e 100644 --- a/lib/Sema/ParseAST.cpp +++ b/lib/Sema/ParseAST.cpp @@ -29,14 +29,15 @@ using namespace clang; /// held by Ctx. /// void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, - ASTContext &Ctx, bool PrintStats) { + ASTContext &Ctx, bool PrintStats, + bool CompleteTranslationUnit) { // Collect global stats on Decls/Stmts (until we have a module streamer). if (PrintStats) { Decl::CollectingStats(true); Stmt::CollectingStats(true); } - Sema S(PP, Ctx, *Consumer); + Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit); Parser P(PP, S); PP.EnterMainSourceFile(); diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index f11ce2043a..403e8f60f5 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -151,12 +151,14 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { Context.setObjCIdType(IdTypedef); } -Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer) +Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, + bool CompleteTranslationUnit) : LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), CurContext(0), PreDeclaratorDC(0), CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()), - GlobalNewDeleteDeclared(false) { + GlobalNewDeleteDeclared(false), + CompleteTranslationUnit(CompleteTranslationUnit) { // Get IdentifierInfo objects for known functions for which we // do extra checking. @@ -216,6 +218,9 @@ void Sema::DeleteStmt(StmtTy *S) { /// translation unit when EOF is reached and all but the top-level scope is /// popped. void Sema::ActOnEndOfTranslationUnit() { + if (!CompleteTranslationUnit) + return; + // C99 6.9.2p2: // A declaration of an identifier for an object that has file // scope without an initializer, and without a storage-class diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index f48e75afb3..d64228794b 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -214,7 +214,18 @@ public: /// A flag to remember whether the implicit forms of operator new and delete /// have been declared. bool GlobalNewDeleteDeclared; - + + /// \brief Whether the code handled by Sema should be considered a + /// complete translation unit or not. + /// + /// When true (which is generally the case), Sema will perform + /// end-of-translation-unit semantic tasks (such as creating + /// initializers for tentative definitions in C) once parsing has + /// completed. This flag will be false when building PCH files, + /// since a PCH file is by definition not a complete translation + /// unit. + bool CompleteTranslationUnit; + /// ObjCMethodList - a linked list of methods with different signatures. struct ObjCMethodList { ObjCMethodDecl *Method; @@ -239,7 +250,8 @@ public: /// Private Helper predicate to check for 'self'. bool isSelfExpr(Expr *RExpr); public: - Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer); + Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, + bool CompleteTranslationUnit = true); ~Sema() { if (PackContext) FreePackedContext(); } diff --git a/test/PCH/external-defs.c b/test/PCH/external-defs.c index 7be6c73bc7..fd14c4fa8b 100644 --- a/test/PCH/external-defs.c +++ b/test/PCH/external-defs.c @@ -2,7 +2,20 @@ // RUN: clang-cc -triple x86_64-apple-darwin9 -emit-pch -o %t.pch %S/external-defs.h && // RUN: clang-cc -triple x86_64-apple-darwin9 -include-pch %t.pch -emit-llvm -o %t %s && -// RUN: grep "@x = common global i32 0, align 4" %t | count 1 && +// RUN: grep "@x = common global i32 0" %t | count 1 && // FIXME below: should be i32 17, but we don't serialize y's value yet -// RUN: grep "@y = common global i32 0, align 4" %t | count 1 && -// RUN: grep "@z" %t | count 0 +// RUN: grep "@y = common global i32 0" %t | count 1 && +// RUN: grep "@z" %t | count 0 && + +// RUN: grep "@x2 = global i32 19" %t | count 1 && +int x2 = 19; + +// RUN: grep "@incomplete_array = common global .*1 x i32" %t | count 1 && +// RUN: grep "@incomplete_array2 = common global .*17 x i32" %t | count 1 && +int incomplete_array2[17]; +// RUN: grep "@incomplete_array3 = common global .*1 x i32" %t | count 1 +int incomplete_array3[]; + +struct S { + int x, y; +}; diff --git a/test/PCH/external-defs.h b/test/PCH/external-defs.h index 29345e9c69..4ac9077d12 100644 --- a/test/PCH/external-defs.h +++ b/test/PCH/external-defs.h @@ -1,10 +1,17 @@ // Helper for external-defs.c test -// Tentative definition +// Tentative definitions int x; +int x2; // FIXME: check this, once we actually serialize it int y = 17; // Should not show up static int z; + +int incomplete_array[]; +int incomplete_array2[]; + +// FIXME: CodeGen problems prevents this from working () +// struct S s; diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp index 91b87f2b05..3360649475 100644 --- a/tools/clang-cc/clang-cc.cpp +++ b/tools/clang-cc/clang-cc.cpp @@ -1912,6 +1912,7 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF, llvm::OwningPtr Consumer; bool ClearSourceMgr = false; FixItRewriter *FixItRewrite = 0; + bool CompleteTranslationUnit = true; switch (PA) { default: @@ -1925,6 +1926,8 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF, return; } + if (ProgAction == GeneratePCH) + CompleteTranslationUnit = false; break; case DumpRawTokens: { @@ -2098,7 +2101,8 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF, return; } - ParseAST(PP, Consumer.get(), *ContextOwner.get(), Stats); + ParseAST(PP, Consumer.get(), *ContextOwner.get(), Stats, + CompleteTranslationUnit); if (FixItRewrite) FixItRewrite->WriteFixedFile(InFile, OutputFile); -- 2.40.0