[cfe-commits] r43567 - in /cfe/trunk: Lex/Preprocessor.cpp Parse/MinimalAction.cpp Sema/Sema.cpp Sema/Sema.h Sema/SemaDecl.cpp Sema/SemaExpr.cpp clang.xcodeproj/project.pbxproj include/clang/Parse/Action.h
Steve Naroff
snaroff at apple.com
Wed Oct 31 11:42:27 PDT 2007
Author: snaroff
Date: Wed Oct 31 13:42:27 2007
New Revision: 43567
URL: http://llvm.org/viewvc/llvm-project?rev=43567&view=rev
Log:
Implement a more sensible strategy for ObjC built-in types (addressing a long standing FIXME in Sema::GetObjcIdType()).
This removes several gross hacks to work around the previous "lazy" behavior.
Two notes:
- MinimalActions still needs to be taught about the built-in types (This breaks one of the -noop test cases). I started this, then added a FIXME.
- I didn't convert Sema::GetObjcProtoType() yet.
Modified:
cfe/trunk/Lex/Preprocessor.cpp
cfe/trunk/Parse/MinimalAction.cpp
cfe/trunk/Sema/Sema.cpp
cfe/trunk/Sema/Sema.h
cfe/trunk/Sema/SemaDecl.cpp
cfe/trunk/Sema/SemaExpr.cpp
cfe/trunk/clang.xcodeproj/project.pbxproj
cfe/trunk/include/clang/Parse/Action.h
Modified: cfe/trunk/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Lex/Preprocessor.cpp?rev=43567&r1=43566&r2=43567&view=diff
==============================================================================
--- cfe/trunk/Lex/Preprocessor.cpp (original)
+++ cfe/trunk/Lex/Preprocessor.cpp Wed Oct 31 13:42:27 2007
@@ -369,33 +369,7 @@
DefineBuiltinMacro(Buf, "__OBJC__=1");
if (PP.getLangOptions().ObjC2)
DefineBuiltinMacro(Buf, "__OBJC2__=1");
- if (PP.getLangOptions().ObjC1) {
- const char *ObjcType;
- // Predefine all the ObjC goodies (traditionally declared in <objc/objc.h>).
- // We define the following header guard for source compatibility. It has
- // the effect of ignoring any explicit inclusion of <objc/objc.h>:-)
- DefineBuiltinMacro(Buf, "_OBJC_OBJC_H_=1");
- DefineBuiltinMacro(Buf, "OBJC_EXPORT=extern");
- DefineBuiltinMacro(Buf, "OBJC_IMPORT=extern");
- ObjcType = "typedef struct objc_class *Class;\n";
- Buf.insert(Buf.end(), ObjcType, ObjcType+strlen(ObjcType));
- ObjcType = "typedef struct objc_object { Class isa; } *id;\n";
- Buf.insert(Buf.end(), ObjcType, ObjcType+strlen(ObjcType));
- ObjcType = "typedef struct objc_selector *SEL;\n";
- Buf.insert(Buf.end(), ObjcType, ObjcType+strlen(ObjcType));
- ObjcType = "typedef id (*IMP)(id, SEL, ...);\n";
- Buf.insert(Buf.end(), ObjcType, ObjcType+strlen(ObjcType));
- ObjcType = "typedef signed char BOOL;\n";
- Buf.insert(Buf.end(), ObjcType, ObjcType+strlen(ObjcType));
- DefineBuiltinMacro(Buf, "YES=(BOOL)1");
- DefineBuiltinMacro(Buf, "NO=(BOOL)0");
- DefineBuiltinMacro(Buf, "Nil=0");
- DefineBuiltinMacro(Buf, "nil=0");
- ObjcType = "extern const char *sel_getName(SEL sel);\n";
- Buf.insert(Buf.end(), ObjcType, ObjcType+strlen(ObjcType));
- ObjcType = "extern SEL sel_getUid(const char *str);\n";
- Buf.insert(Buf.end(), ObjcType, ObjcType+strlen(ObjcType));
- }
+
// Add __builtin_va_list typedef.
{
const char *VAList = PP.getTargetInfo().getVAListDeclaration();
Modified: cfe/trunk/Parse/MinimalAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/MinimalAction.cpp?rev=43567&r1=43566&r2=43567&view=diff
==============================================================================
--- cfe/trunk/Parse/MinimalAction.cpp (original)
+++ cfe/trunk/Parse/MinimalAction.cpp Wed Oct 31 13:42:27 2007
@@ -28,6 +28,11 @@
}
};
+void MinimalAction:: ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
+ TUScope = S;
+ // FIXME: add id/SEL/Class. We need to get our paws on the identifier table.
+}
+
/// isTypeName - This looks at the IdentifierInfo::FETokenInfo field to
/// determine whether the name is a type name (objc class name or typedef) or
/// not in this scope.
Modified: cfe/trunk/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.cpp?rev=43567&r1=43566&r2=43567&view=diff
==============================================================================
--- cfe/trunk/Sema/Sema.cpp (original)
+++ cfe/trunk/Sema/Sema.cpp Wed Oct 31 13:42:27 2007
@@ -16,54 +16,35 @@
#include "clang/AST/ASTContext.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Parse/Scope.h"
using namespace clang;
-void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
- TUScope = S;
+bool Sema::isBuiltinObjcType(TypedefDecl *TD) {
+ const char *typeName = TD->getIdentifier()->getName();
+ return strcmp(typeName, "id") == 0 || strcmp(typeName, "Class") == 0 ||
+ strcmp(typeName, "SEL") == 0;
}
-/// 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 (!Context.getObjcIdType().isNull())
- return Context.getObjcIdType();
+void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
+ TUScope = S;
+ if (PP.getLangOptions().ObjC1) {
+ TypedefType *t;
- IdentifierInfo *IdIdent = &Context.Idents.get("id");
- ScopedDecl *IdDecl = LookupScopedDecl(IdIdent, Decl::IDNS_Ordinary,
- SourceLocation(), TUScope);
- TypedefDecl *ObjcIdTypedef = dyn_cast_or_null<TypedefDecl>(IdDecl);
- if (!ObjcIdTypedef) {
- Diag(Loc, diag::err_missing_id_definition);
- return QualType();
- }
- Context.setObjcIdType(ObjcIdTypedef);
- return Context.getObjcIdType();
-}
-
-/// GetObjcSelType - See comments for Sema::GetObjcIdType above; replace "id"
-/// with "SEL".
-QualType Sema::GetObjcSelType(SourceLocation Loc) {
- assert(TUScope && "GetObjcSelType(): Top-level scope is null");
- if (Context.getObjcSelType().isNull()) {
- IdentifierInfo *SelIdent = &Context.Idents.get("SEL");
- ScopedDecl *SelDecl = LookupScopedDecl(SelIdent, Decl::IDNS_Ordinary,
- SourceLocation(), TUScope);
- TypedefDecl *ObjcSelTypedef = dyn_cast_or_null<TypedefDecl>(SelDecl);
- if (!ObjcSelTypedef) {
- Diag(Loc, diag::err_missing_sel_definition);
- return QualType();
- }
- Context.setObjcSelType(ObjcSelTypedef);
+ // Add the built-in ObjC types.
+ t = dyn_cast<TypedefType>(Context.getObjcIdType().getTypePtr());
+ t->getDecl()->getIdentifier()->setFETokenInfo(t->getDecl());
+ TUScope->AddDecl(t->getDecl());
+ t = dyn_cast<TypedefType>(Context.getObjcClassType().getTypePtr());
+ t->getDecl()->getIdentifier()->setFETokenInfo(t->getDecl());
+ TUScope->AddDecl(t->getDecl());
+ t = dyn_cast<TypedefType>(Context.getObjcSelType().getTypePtr());
+ t->getDecl()->getIdentifier()->setFETokenInfo(t->getDecl());
+ TUScope->AddDecl(t->getDecl());
}
- return Context.getObjcSelType();
}
+/// FIXME: remove this.
/// GetObjcProtoType - See comments for Sema::GetObjcIdType above; replace "id"
/// with "Protocol".
QualType Sema::GetObjcProtoType(SourceLocation Loc) {
@@ -82,25 +63,6 @@
return Context.getObjcProtoType();
}
-/// GetObjcClassType - See comments for Sema::GetObjcIdType above; replace "id"
-/// with "Protocol".
-QualType Sema::GetObjcClassType(SourceLocation Loc) {
- assert(TUScope && "GetObjcClassType(): Top-level scope is null");
- if (!Context.getObjcClassType().isNull())
- return Context.getObjcClassType();
-
- IdentifierInfo *ClassIdent = &Context.Idents.get("Class");
- ScopedDecl *ClassDecl = LookupScopedDecl(ClassIdent, Decl::IDNS_Ordinary,
- SourceLocation(), TUScope);
- TypedefDecl *ObjcClassTypedef = dyn_cast_or_null<TypedefDecl>(ClassDecl);
- if (!ObjcClassTypedef) {
- Diag(Loc, diag::err_missing_class_definition);
- return QualType();
- }
- Context.setObjcClassType(ObjcClassTypedef);
- return Context.getObjcClassType();
-}
-
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup)
: PP(pp), Context(ctxt), CurFunctionDecl(0), LastInGroupList(prevInGroup) {
@@ -118,7 +80,38 @@
KnownFunctionIDs[ id_vfprintf ] = &IT.get("vfprintf");
KnownFunctionIDs[ id_vsprintf ] = &IT.get("vsprintf");
KnownFunctionIDs[ id_vprintf ] = &IT.get("vprintf");
-
+
+ if (PP.getLangOptions().ObjC1) {
+ // Synthesize "typedef struct objc_class *Class;"
+ RecordDecl *ClassTag = new RecordDecl(Decl::Struct, SourceLocation(),
+ &IT.get("objc_class"), 0);
+ QualType ClassT = Context.getPointerType(Context.getTagDeclType(ClassTag));
+ TypedefDecl *ClassTypedef = new TypedefDecl(SourceLocation(),
+ &Context.Idents.get("Class"),
+ ClassT, 0);
+ Context.setObjcClassType(ClassTypedef);
+
+ // Synthesize "typedef struct objc_object { Class isa; } *id;"
+ RecordDecl *ObjectTag = new RecordDecl(Decl::Struct, SourceLocation(),
+ &IT.get("objc_object"), 0);
+ FieldDecl *IsaDecl = new FieldDecl(SourceLocation(), 0,
+ Context.getObjcClassType());
+ ObjectTag->defineBody(&IsaDecl, 1);
+ QualType ObjT = Context.getPointerType(Context.getTagDeclType(ObjectTag));
+ TypedefDecl *IdTypedef = new TypedefDecl(SourceLocation(),
+ &Context.Idents.get("id"),
+ ObjT, 0);
+ Context.setObjcIdType(IdTypedef);
+
+ // Synthesize "typedef struct objc_selector *SEL;"
+ RecordDecl *SelTag = new RecordDecl(Decl::Struct, SourceLocation(),
+ &IT.get("objc_selector"), 0);
+ QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag));
+ TypedefDecl *SelTypedef = new TypedefDecl(SourceLocation(),
+ &Context.Idents.get("SEL"),
+ SelT, 0);
+ Context.setObjcSelType(SelTypedef);
+ }
TUScope = 0;
}
Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=43567&r1=43566&r2=43567&view=diff
==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Wed Oct 31 13:42:27 2007
@@ -275,17 +275,11 @@
bool MatchTwoMethodDeclarations(const ObjcMethodDecl *Method,
const ObjcMethodDecl *PrevMethod);
- /// GetObjcIdType - Getter for the build-in "id" type.
- QualType GetObjcIdType(SourceLocation Loc = SourceLocation());
-
- /// GetObjcSelType - Getter for the build-in "SEL" type.
- QualType GetObjcSelType(SourceLocation Loc = SourceLocation());
-
/// GetObjcSelType - Getter for the build-in "Protocol *" type.
QualType GetObjcProtoType(SourceLocation Loc = SourceLocation());
- // GetObjcClassType - Getter for the built-in "Class" type.
- QualType GetObjcClassType(SourceLocation Loc = SourceLocation());
+ /// isBuiltinObjcType - Returns true of the type is "id", "SEL", "Class".
+ bool isBuiltinObjcType(TypedefDecl *TD);
/// AddInstanceMethodToGlobalPool - All instance methods in a translation
/// unit are added to a global pool. This allows us to efficiently associate
Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=43567&r1=43566&r2=43567&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Wed Oct 31 13:42:27 2007
@@ -25,6 +25,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/DenseSet.h"
+#include "clang/Lex/Preprocessor.h"
using namespace clang;
Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
@@ -210,6 +211,11 @@
return New;
}
+ // Allow multiple definitions for ObjC built-in typedefs.
+ // FIXME: Verify the underlying types are equivalent!
+ if (PP.getLangOptions().ObjC1 && isBuiltinObjcType(New))
+ return Old;
+
// TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
// TODO: This is totally simplistic. It should handle merging functions
// together etc, merging extern int X; int X; ...
@@ -1193,17 +1199,7 @@
/// Check that class of this category is already completely declared.
if (!IDecl || IDecl->isForwardDecl())
Diag(ClassLoc, diag::err_undef_interface, ClassName->getName());
-
- // We cannot build type 'id' lazily. It is needed when checking if a
- // type is an 'id' (via call to isObjcIdType) even if there is no
- // need for the default 'id' type.
- // FIXME: Depending on the need to compare to 'id', this may have to go
- // somewhere else. At this time, this is a good enough place to do type
- // encoding of methods and ivars for the rewrite client.
- GetObjcIdType(AtCatImplLoc);
- GetObjcClassType(AtCatImplLoc);
- GetObjcSelType(AtCatImplLoc);
-
+
/// TODO: Check that CatName, category name, is not used in another
// implementation.
return CDecl;
@@ -1273,16 +1269,6 @@
if (!ObjcImplementations.insert(ClassName))
Diag(ClassLoc, diag::err_dup_implementation_class, ClassName->getName());
- // We cannot build type 'id' laziliy. It is needed when checking if a
- // type is an 'id' (via call to isObjcIdType) even if there is no
- // need for the dafult 'id' type.
- // FIXME: Depending on the need to compare to 'id', this may have to go
- // somewhere else. At this time, this is a good enough place to do type
- // encoding of methods and ivars for the rewrite client.
- GetObjcIdType(AtClassImplLoc);
- GetObjcClassType(AtClassImplLoc);
- GetObjcSelType(AtClassImplLoc);
-
return IMPDecl;
}
@@ -1992,7 +1978,7 @@
if (ArgTypes[i])
argType = QualType::getFromOpaquePtr(ArgTypes[i]);
else
- argType = GetObjcIdType(MethodLoc);
+ argType = Context.getObjcIdType();
ParmVarDecl* Param = new ParmVarDecl(SourceLocation(/*FIXME*/), ArgNames[i],
argType, VarDecl::None, 0);
Params.push_back(Param);
@@ -2002,7 +1988,7 @@
if (ReturnType)
resultDeclType = QualType::getFromOpaquePtr(ReturnType);
else // get the type for "id".
- resultDeclType = GetObjcIdType(MethodLoc);
+ resultDeclType = Context.getObjcIdType();
ObjcMethodDecl* ObjcMethod = new ObjcMethodDecl(MethodLoc, EndLoc, Sel,
resultDeclType, 0, -1, AttrList,
Modified: cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaExpr.cpp?rev=43567&r1=43566&r2=43567&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Wed Oct 31 13:42:27 2007
@@ -1959,17 +1959,6 @@
SourceLocation RParenLoc) {
QualType EncodedType = QualType::getFromOpaquePtr(Ty);
- // We cannot build type 'id' lazily. It is needed when checking if a
- // type is an 'id' (via call to isObjcIdType) even if there is no
- // need for the default 'id' type.
- // FIXME: Depending on the need to compare to 'id', this may have to go
- // somewhere else. At this time, this is a good enough place to do type
- // encoding of methods and ivars for the rewrite client.
- // The same is true for the 'Class' and 'SEL' types.
- GetObjcIdType(EncodeLoc);
- GetObjcClassType(EncodeLoc);
- GetObjcSelType(EncodeLoc);
-
QualType t = Context.getPointerType(Context.CharTy);
return new ObjCEncodeExpr(t, EncodedType, AtLoc, RParenLoc);
}
@@ -1979,7 +1968,7 @@
SourceLocation SelLoc,
SourceLocation LParenLoc,
SourceLocation RParenLoc) {
- QualType t = GetObjcSelType(AtLoc);
+ QualType t = Context.getObjcSelType();
return new ObjCSelectorExpr(t, Sel, AtLoc, RParenLoc);
}
@@ -2076,7 +2065,7 @@
if (!Method) {
Diag(lbrac, diag::warn_method_not_found, std::string("+"), Sel.getName(),
SourceRange(lbrac, rbrac));
- returnType = GetObjcIdType();
+ returnType = Context.getObjcIdType();
} else {
returnType = Method->getResultType();
if (Sel.getNumArgs()) {
@@ -2084,7 +2073,6 @@
return true;
}
}
- GetObjcSelType(lbrac); // FIXME: a hack to install the sel type.
return new ObjCMessageExpr(receiverName, Sel, returnType, lbrac, rbrac,
ArgExprs);
}
@@ -2103,12 +2091,12 @@
QualType receiverType = RExpr->getType();
QualType returnType;
- if (receiverType == GetObjcIdType()) {
+ if (receiverType == Context.getObjcIdType()) {
ObjcMethodDecl *Method = InstanceMethodPool[Sel].Method;
if (!Method) {
Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(),
SourceRange(lbrac, rbrac));
- returnType = GetObjcIdType();
+ returnType = Context.getObjcIdType();
} else {
returnType = Method->getResultType();
if (Sel.getNumArgs())
@@ -2134,7 +2122,7 @@
if (!Method) {
Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(),
SourceRange(lbrac, rbrac));
- returnType = GetObjcIdType();
+ returnType = Context.getObjcIdType();
} else {
returnType = Method->getResultType();
if (Sel.getNumArgs())
@@ -2142,6 +2130,5 @@
return true;
}
}
- GetObjcSelType(lbrac); // FIXME: a hack to install the sel type.
return new ObjCMessageExpr(RExpr, Sel, returnType, lbrac, rbrac, ArgExprs);
}
Modified: cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=43567&r1=43566&r2=43567&view=diff
==============================================================================
--- cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/trunk/clang.xcodeproj/project.pbxproj Wed Oct 31 13:42:27 2007
@@ -756,7 +756,6 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
- compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
projectDirPath = "";
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=43567&r1=43566&r2=43567&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Wed Oct 31 13:42:27 2007
@@ -645,9 +645,7 @@
/// ActOnPopScope - When a scope is popped, if any typedefs are now
/// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field.
virtual void ActOnPopScope(SourceLocation Loc, Scope *S);
- virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
- TUScope = S;
- }
+ virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S);
virtual DeclTy *ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
More information about the cfe-commits
mailing list