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
This commit is contained in:
Douglas Gregor 2009-07-07 16:35:42 +00:00
Родитель 0d3c26c769
Коммит c29f77b769
7 изменённых файлов: 62 добавлений и 11 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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<TypeDecl>(*Lookup.first)) {
Type = Context.getTypeDeclType(cast<TypeDecl>(*Lookup.first));
break;
}
else {
Type = Context.getFILEType();
if (Type.isNull()) {
Error = ASTContext::GE_Missing_FILE;
return QualType();
} else {
break;
}
}
}

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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