//===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the actions class which performs semantic analysis and // builds an AST out of a parse stream. // //===----------------------------------------------------------------------===// #include "Sema.h" #include "clang/AST/ASTContext.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Parse/Scope.h" using namespace clang; bool Sema::isBuiltinObjCType(TypedefDecl *TD) { const char *typeName = TD->getIdentifier()->getName(); return strcmp(typeName, "id") == 0 || strcmp(typeName, "Class") == 0 || strcmp(typeName, "SEL") == 0 || strcmp(typeName, "Protocol") == 0; } /// isObjCObjectPointerType - Returns true if type is an Objective-C pointer /// to an object type. This includes "id" and "Class" (two 'special' pointers /// to struct), Interface* (pointer to ObjCInterfaceType) and id
(qualified
/// ID type).
bool Sema::isObjCObjectPointerType(QualType Ty) const {
if (Ty->isObjCQualifiedIdType())
return true;
if (!Ty->isPointerType())
return false;
// Check to see if this is 'id' or 'Class', both of which are typedefs for
// pointer types. This looks for the typedef specifically, not for the
// underlying type.
if (Ty == Context.getObjCIdType() || Ty == Context.getObjCClassType())
return true;
// If this a pointer to an interface (e.g. NSString*), it is ok.
return Ty->getAsPointerType()->getPointeeType()->isObjCInterfaceType();
}
void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
TUScope = S;
CurContext = Context.getTranslationUnitDecl();
if (!PP.getLangOptions().ObjC1) return;
// Synthesize "typedef struct objc_selector *SEL;"
RecordDecl *SelTag = RecordDecl::Create(Context, TagDecl::TK_struct,
CurContext,
SourceLocation(),
&Context.Idents.get("objc_selector"),
0);
PushOnScopeChains(SelTag, TUScope);
QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag));
TypedefDecl *SelTypedef = TypedefDecl::Create(Context, CurContext,
SourceLocation(),
&Context.Idents.get("SEL"),
SelT, 0);
PushOnScopeChains(SelTypedef, TUScope);
Context.setObjCSelType(SelTypedef);
// FIXME: Make sure these don't leak!
RecordDecl *ClassTag = RecordDecl::Create(Context, TagDecl::TK_struct,
CurContext,
SourceLocation(),
&Context.Idents.get("objc_class"),
0);
QualType ClassT = Context.getPointerType(Context.getTagDeclType(ClassTag));
TypedefDecl *ClassTypedef =
TypedefDecl::Create(Context, CurContext, SourceLocation(),
&Context.Idents.get("Class"), ClassT, 0);
PushOnScopeChains(ClassTag, TUScope);
PushOnScopeChains(ClassTypedef, TUScope);
Context.setObjCClassType(ClassTypedef);
// Synthesize "@class Protocol;
ObjCInterfaceDecl *ProtocolDecl =
ObjCInterfaceDecl::Create(Context, SourceLocation(),
&Context.Idents.get("Protocol"),
SourceLocation(), true);
Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
PushOnScopeChains(ProtocolDecl, TUScope);
// Synthesize "typedef struct objc_object { Class isa; } *id;"
RecordDecl *ObjectTag =
RecordDecl::Create(Context, TagDecl::TK_struct, CurContext,
SourceLocation(),
&Context.Idents.get("objc_object"), 0);
QualType ObjT = Context.getPointerType(Context.getTagDeclType(ObjectTag));
PushOnScopeChains(ObjectTag, TUScope);
TypedefDecl *IdTypedef = TypedefDecl::Create(Context, CurContext,
SourceLocation(),
&Context.Idents.get("id"),
ObjT, 0);
PushOnScopeChains(IdTypedef, TUScope);
Context.setObjCIdType(IdTypedef);
}
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer)
: PP(pp), Context(ctxt), Consumer(consumer), CurContext(0) {
// Get IdentifierInfo objects for known functions for which we
// do extra checking.
IdentifierTable &IT = PP.getIdentifierTable();
KnownFunctionIDs[id_printf] = &IT.get("printf");
KnownFunctionIDs[id_fprintf] = &IT.get("fprintf");
KnownFunctionIDs[id_sprintf] = &IT.get("sprintf");
KnownFunctionIDs[id_snprintf] = &IT.get("snprintf");
KnownFunctionIDs[id_asprintf] = &IT.get("asprintf");
KnownFunctionIDs[id_NSLog] = &IT.get("NSLog");
KnownFunctionIDs[id_vsnprintf] = &IT.get("vsnprintf");
KnownFunctionIDs[id_vasprintf] = &IT.get("vasprintf");
KnownFunctionIDs[id_vfprintf] = &IT.get("vfprintf");
KnownFunctionIDs[id_vsprintf] = &IT.get("vsprintf");
KnownFunctionIDs[id_vprintf] = &IT.get("vprintf");
TUScope = 0;
if (getLangOptions().CPlusPlus)
FieldCollector.reset(new CXXFieldCollector());
}
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
/// If there is already an implicit cast, merge into the existing one.
void Sema::ImpCastExprToType(Expr *&Expr, QualType Type) {
if (Expr->getType().getCanonicalType() == Type.getCanonicalType()) return;
if (ImplicitCastExpr *ImpCast = dyn_cast