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
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
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.
/// \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.
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) {
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;
}
}
}
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
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.
}
}
}
+
+ // 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;
}
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);
}
// 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, ...);
{
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