Refinements to Sema::GetObjcIdType()...
- Cache the typedef, not the type (avoids importing AST/Type.h).
- Emit an error if "id" cannot be found.
- Comment the routine and add a FIXME to reconsider how we emulate GCC's new fangled behavior. This isn't a priority for now, since almost no code depends on having "id" built-in.
- Add a test.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42845 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Sema/Sema.cpp b/Sema/Sema.cpp
index f34aa63..9487ed0 100644
--- a/Sema/Sema.cpp
+++ b/Sema/Sema.cpp
@@ -23,17 +23,25 @@
TUScope = S;
}
-QualType Sema::GetObjcIdType() {
+/// GetObjcIdType - The following method assumes that "id" is imported
+/// via <objc/objc.h>. This is the way GCC worked for almost 20 years.
+/// In GCC 4.0, "id" is now a built-in type. Unfortunately, typedefs *cannot* be
+/// redefined (even if they are identical). To allow a built-in types to coexist
+/// with <objc/objc.h>, GCC has a special hack on decls (DECL_IN_SYSTEM_HEADER).
+/// For now, we will *not* install id as a built-in. FIXME: reconsider this.
+QualType Sema::GetObjcIdType(SourceLocation Loc) {
assert(TUScope && "GetObjcIdType(): Top-level scope is null");
- if (ObjcIdType.isNull()) {
+ if (!ObjcIdTypedef) {
IdentifierInfo *IdIdent = &Context.Idents.get("id");
ScopedDecl *IdDecl = LookupScopedDecl(IdIdent, Decl::IDNS_Ordinary,
SourceLocation(), TUScope);
- TypedefDecl *IdTypedef = dyn_cast_or_null<TypedefDecl>(IdDecl);
- assert(IdTypedef && "GetObjcIdType(): Couldn't find 'id' type");
- ObjcIdType = Context.getTypedefType(IdTypedef);
+ ObjcIdTypedef = dyn_cast_or_null<TypedefDecl>(IdDecl);
+ if (!ObjcIdTypedef) {
+ Diag(Loc, diag::err_missing_id_definition);
+ return QualType();
+ }
}
- return ObjcIdType;
+ return Context.getTypedefType(ObjcIdTypedef);
}
@@ -56,7 +64,7 @@
KnownFunctionIDs[ id_vprintf ] = &IT.get("vprintf");
TUScope = 0;
- ObjcIdType = QualType();
+ ObjcIdTypedef = 0;
}
void Sema::DeleteExpr(ExprTy *E) {
diff --git a/Sema/Sema.h b/Sema/Sema.h
index 0ac513e..0eb803e 100644
--- a/Sema/Sema.h
+++ b/Sema/Sema.h
@@ -19,7 +19,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
-#include "clang/AST/Type.h"
#include <vector>
#include <string>
@@ -119,8 +118,8 @@
/// For example, user-defined classes, built-in "id" type, etc.
Scope *TUScope;
- /// ObjcIdType - built-in type for "id".
- QualType ObjcIdType;
+ /// ObjcIdTypedef - built-in typedef for "id".
+ TypedefDecl *ObjcIdTypedef;
public:
Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup);
@@ -257,7 +256,7 @@
const ObjcMethodDecl *PrevMethod);
/// GetObjcIdType - Getter for the build-in "id" type.
- QualType GetObjcIdType();
+ QualType GetObjcIdType(SourceLocation Loc = SourceLocation());
//===--------------------------------------------------------------------===//
// Statement Parsing Callbacks: SemaStmt.cpp.
diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp
index eb1b158..1d15d7b 100644
--- a/Sema/SemaDecl.cpp
+++ b/Sema/SemaDecl.cpp
@@ -1779,7 +1779,7 @@
if (ArgTypes[i])
argType = QualType::getFromOpaquePtr(ArgTypes[i]);
else
- argType = GetObjcIdType();
+ argType = GetObjcIdType(MethodLoc);
ParmVarDecl* Param = new ParmVarDecl(SourceLocation(/*FIXME*/), ArgNames[i],
argType, VarDecl::None, 0);
Params.push_back(Param);
@@ -1789,7 +1789,7 @@
if (ReturnType)
resultDeclType = QualType::getFromOpaquePtr(ReturnType);
else // get the type for "id".
- resultDeclType = GetObjcIdType();
+ resultDeclType = GetObjcIdType(MethodLoc);
ObjcMethodDecl* ObjcMethod = new ObjcMethodDecl(MethodLoc, Sel,
resultDeclType, 0, -1, AttrList,
diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj
index c7f4908..b5cf88f 100644
--- a/clang.xcodeproj/project.pbxproj
+++ b/clang.xcodeproj/project.pbxproj
@@ -739,7 +739,6 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
- compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
projectDirPath = "";
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index b71a6a6..adc2425 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -444,6 +444,8 @@
"previous declaration is here")
DIAG(err_undeclared_protocol, ERROR,
"cannot find protocol declaration for '%0'")
+DIAG(err_missing_id_definition, ERROR,
+ "cannot find definition of 'id'")
//===----------------------------------------------------------------------===//
diff --git a/test/Sema/id_not_builtin.m b/test/Sema/id_not_builtin.m
new file mode 100644
index 0000000..81988fa
--- /dev/null
+++ b/test/Sema/id_not_builtin.m
@@ -0,0 +1,9 @@
+// RUN: clang %s -parse-ast -verify
+
+id obj; // expected-error{{expected '=', ',', ';', 'asm', or '__attribute__' after declarator}}
+
+@interface Foo
+
+- defaultToId; // expected-error{{cannot find definition of 'id'}}
+
+@end