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.

llvm-svn: 69043
This commit is contained in:
Douglas Gregor 2009-04-14 16:27:31 +00:00
parent 06f440dd7b
commit 54feb84489
7 changed files with 63 additions and 15 deletions

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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();
}

View File

@ -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;
};

View File

@ -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 (<rdar://problem/6762287>)
// struct S s;

View File

@ -1912,6 +1912,7 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
llvm::OwningPtr<ASTConsumer> 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);