From c29f77b769bcc5b6dc85e72c8e3cc2e348e5cf25 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 7 Jul 2009 16:35:42 +0000 Subject: [PATCH] Make ASTContext explicitly keep track of the declaration for the C FILE type, rather than using name lookup to find FILE within the translation unit. Within precompiled headers, FILE is treated as yet another "special type" (like __builtin_va_list). This change should provide a performance improvement (not verified), since the lookup into the translation unit declaration forces the (otherwise unneeded) construction of a large hash table. More importantly, with precompiled headers, the construction of that table requires deserializing most of the top-level declarations from the precompiled header, which are then unused. Fixes PR 4509. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74911 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 13 +++++++++++++ include/clang/Frontend/PCHBitCodes.h | 4 +++- lib/AST/ASTContext.cpp | 15 ++++++--------- lib/Frontend/PCHReader.cpp | 11 +++++++++++ lib/Frontend/PCHWriter.cpp | 1 + lib/Sema/SemaDecl.cpp | 15 +++++++++++++++ test/PCH/pr4489.c | 14 +++++++++++++- 7 files changed, 62 insertions(+), 11 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index e85eac59a7..fbd56023d6 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -126,6 +126,9 @@ class ASTContext { RecordDecl *ObjCFastEnumerationStateTypeDecl; + /// \brief The type for the C FILE type. + TypeDecl *FILEDecl; + /// \brief Keeps track of all declaration attributes. /// /// Since so few decls have attrs, we keep them in a hash map instead of @@ -447,6 +450,16 @@ public: void setObjCFastEnumerationStateType(QualType T); + /// \brief Set the type for the C FILE type. + void setFILEDecl(TypeDecl *FILEDecl) { this->FILEDecl = FILEDecl; } + + /// \brief Retrieve the C FILE type. + QualType getFILEType() { + if (FILEDecl) + return getTypeDeclType(FILEDecl); + return QualType(); + } + /// getObjCEncodingForType - Emit the ObjC type encoding for the /// given type into \arg S. If \arg NameFields is specified then /// record field names are also encoded. diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 8efaf26cc8..0de6b69432 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -419,7 +419,9 @@ namespace clang { /// \brief CFConstantString type SPECIAL_TYPE_CF_CONSTANT_STRING = 5, /// \brief Objective-C fast enumeration state type - SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE = 6 + SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE = 6, + /// \brief C FILE typedef type + SPECIAL_TYPE_FILE = 7 }; /// \brief Record codes for each kind of declaration. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 08607d5ed2..c59a5d703b 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -36,7 +36,8 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, Builtin::Context &builtins, bool FreeMem, unsigned size_reserve) : GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0), - ObjCFastEnumerationStateTypeDecl(0), SourceMgr(SM), LangOpts(LOpts), + ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), + SourceMgr(SM), LangOpts(LOpts), LoadedExternalComments(false), FreeMemory(FreeMem), Target(t), Idents(idents), Selectors(sels), BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) { @@ -3844,16 +3845,12 @@ static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context, break; } case 'P': { - IdentifierInfo *II = &Context.Idents.get("FILE"); - DeclContext::lookup_result Lookup - = Context.getTranslationUnitDecl()->lookup(II); - if (Lookup.first != Lookup.second && isa(*Lookup.first)) { - Type = Context.getTypeDeclType(cast(*Lookup.first)); - break; - } - else { + Type = Context.getFILEType(); + if (Type.isNull()) { Error = ASTContext::GE_Missing_FILE; return QualType(); + } else { + break; } } } diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index bc0e7208d3..47a7e6264a 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1536,6 +1536,17 @@ void PCHReader::InitializeContext(ASTContext &Ctx) { if (unsigned FastEnum = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE]) Context->setObjCFastEnumerationStateType(GetType(FastEnum)); + if (unsigned File = SpecialTypes[pch::SPECIAL_TYPE_FILE]) { + QualType FileType = GetType(File); + assert(!FileType.isNull() && "FILE type is NULL"); + if (const TypedefType *Typedef = FileType->getAsTypedefType()) + Context->setFILEDecl(Typedef->getDecl()); + else { + const TagType *Tag = FileType->getAsTagType(); + assert(Tag && "Invalid FILE type in PCH file"); + Context->setFILEDecl(Tag->getDecl()); + } + } } /// \brief Retrieve the name of the original source file name diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 566df350f6..0362e8a490 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1892,6 +1892,7 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, AddTypeRef(Context.getObjCClassType(), Record); AddTypeRef(Context.getRawCFConstantStringType(), Record); AddTypeRef(Context.getRawObjCFastEnumerationStateType(), Record); + AddTypeRef(Context.getFILEType(), Record); Stream.EmitRecord(pch::SPECIAL_TYPES, Record); // Write the record containing external, unnamed definitions. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index f148e8d0e1..a1ab68ac2a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1691,6 +1691,14 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, } } } + + // If this is the C FILE type, notify the AST context. + if (IdentifierInfo *II = NewTD->getIdentifier()) + if (!NewTD->isInvalidDecl() && + NewTD->getDeclContext()->getLookupContext()->isTranslationUnit() && + II->isStr("FILE")) + Context.setFILEDecl(NewTD); + return NewTD; } @@ -3768,6 +3776,13 @@ CreateNewDecl: CurContext->addDecl(New); } + // If this is the C FILE type, notify the AST context. + if (IdentifierInfo *II = New->getIdentifier()) + if (!New->isInvalidDecl() && + New->getDeclContext()->getLookupContext()->isTranslationUnit() && + II->isStr("FILE")) + Context.setFILEDecl(New); + OwnedDecl = true; return DeclPtrTy::make(New); } diff --git a/test/PCH/pr4489.c b/test/PCH/pr4489.c index 51988113ec..7730819e92 100644 --- a/test/PCH/pr4489.c +++ b/test/PCH/pr4489.c @@ -1,7 +1,8 @@ // RUN: clang -x c-header -o %t.pch %s && // RUN: clang -include %t -x c /dev/null -emit-llvm -S -o - // PR 4489: Crash with PCH - +// PR 4492: Crash with PCH (round two) +// PR 4509: Crash with PCH (round three) typedef struct _IO_FILE FILE; extern int fprintf (struct _IO_FILE *__restrict __stream, __const char *__restrict __format, ...); @@ -25,4 +26,15 @@ void x0(void) { extern char z0; fprintf (0, "a"); +} + +void x1(void) +{ + fprintf (0, "asdf"); +} + +void y1(void) +{ + extern char e; + fprintf (0, "asdf"); } \ No newline at end of file -- 2.40.0