diff options
Diffstat (limited to 'clang/lib/Sema/Sema.cpp')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp new file mode 100644 index 00000000000..4bd04e3a1a5 --- /dev/null +++ b/clang/lib/Sema/Sema.cpp @@ -0,0 +1,222 @@ +//===--- 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; +} + +bool Sema::isObjCObjectPointerType(QualType type) const { + if (!type->isPointerType() && !type->isObjCQualifiedIdType()) + return false; + if (type == Context.getObjCIdType() || type == Context.getObjCClassType() || + type->isObjCQualifiedIdType()) + return true; + + if (type->isPointerType()) { + PointerType *pointerType = static_cast<PointerType*>(type.getTypePtr()); + type = pointerType->getPointeeType(); + } + return (type->isObjCInterfaceType() || type->isObjCQualifiedIdType()); +} + +void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { + TUScope = S; + if (!PP.getLangOptions().ObjC1) return; + + TypedefType *t; + + // Add the built-in ObjC types. + t = cast<TypedefType>(Context.getObjCIdType().getTypePtr()); + t->getDecl()->getIdentifier()->setFETokenInfo(t->getDecl()); + TUScope->AddDecl(t->getDecl()); + t = cast<TypedefType>(Context.getObjCClassType().getTypePtr()); + t->getDecl()->getIdentifier()->setFETokenInfo(t->getDecl()); + TUScope->AddDecl(t->getDecl()); + ObjCInterfaceType *it = cast<ObjCInterfaceType>(Context.getObjCProtoType()); + ObjCInterfaceDecl *IDecl = it->getDecl(); + IDecl->getIdentifier()->setFETokenInfo(IDecl); + TUScope->AddDecl(IDecl); + + // Synthesize "typedef struct objc_selector *SEL;" + RecordDecl *SelTag = RecordDecl::Create(Context, Decl::Struct, + SourceLocation(), + &Context.Idents.get("objc_selector"), + 0); + SelTag->getIdentifier()->setFETokenInfo(SelTag); + TUScope->AddDecl(SelTag); + + QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag)); + TypedefDecl *SelTypedef = TypedefDecl::Create(Context, SourceLocation(), + &Context.Idents.get("SEL"), + SelT, 0); + SelTypedef->getIdentifier()->setFETokenInfo(SelTypedef); + TUScope->AddDecl(SelTypedef); + Context.setObjCSelType(SelTypedef); +} + +Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer) + : PP(pp), Context(ctxt), Consumer(consumer), + CurFunctionDecl(0), CurMethodDecl(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_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"); + + // FIXME: Move this initialization up to Sema::ActOnTranslationUnitScope() + // and make sure the decls get inserted into TUScope! + if (PP.getLangOptions().ObjC1) { + // Synthesize "typedef struct objc_class *Class;" + RecordDecl *ClassTag = RecordDecl::Create(Context, Decl::Struct, + SourceLocation(), + &IT.get("objc_class"), 0); + QualType ClassT = Context.getPointerType(Context.getTagDeclType(ClassTag)); + TypedefDecl *ClassTypedef = + TypedefDecl::Create(Context, SourceLocation(), + &Context.Idents.get("Class"), ClassT, 0); + Context.setObjCClassType(ClassTypedef); + + // Synthesize "@class Protocol; + ObjCInterfaceDecl *ProtocolDecl = new ObjCInterfaceDecl(SourceLocation(), 0, + &Context.Idents.get("Protocol"), true); + Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl)); + + // Synthesize "typedef struct objc_object { Class isa; } *id;" + RecordDecl *ObjectTag = + RecordDecl::Create(Context, 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 = TypedefDecl::Create(Context, SourceLocation(), + &Context.Idents.get("id"), + ObjT, 0); + Context.setObjCIdType(IdTypedef); + } + TUScope = 0; +} + +/// 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<ImplicitCastExpr>(Expr)) + ImpCast->setType(Type); + else + Expr = new ImplicitCastExpr(Type, Expr); +} + + + +void Sema::DeleteExpr(ExprTy *E) { + delete static_cast<Expr*>(E); +} +void Sema::DeleteStmt(StmtTy *S) { + delete static_cast<Stmt*>(S); +} + +//===----------------------------------------------------------------------===// +// Helper functions. +//===----------------------------------------------------------------------===// + +bool Sema::Diag(SourceLocation Loc, unsigned DiagID) { + PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID); + return true; +} + +bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg) { + PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, &Msg, 1); + return true; +} + +bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1, + const std::string &Msg2) { + std::string MsgArr[] = { Msg1, Msg2 }; + PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, MsgArr, 2); + return true; +} + +bool Sema::Diag(SourceLocation Loc, unsigned DiagID, SourceRange Range) { + PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, 0, 0, &Range,1); + return true; +} + +bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg, + SourceRange Range) { + PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, &Msg, 1, &Range,1); + return true; +} + +bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1, + const std::string &Msg2, SourceRange Range) { + std::string MsgArr[] = { Msg1, Msg2 }; + PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, MsgArr, 2, &Range, 1); + return true; +} + +bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1, + const std::string &Msg2, const std::string &Msg3, + SourceRange R1) { + std::string MsgArr[] = { Msg1, Msg2, Msg3 }; + PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, MsgArr, 3, &R1, 1); + return true; +} + +bool Sema::Diag(SourceLocation Loc, unsigned DiagID, + SourceRange R1, SourceRange R2) { + SourceRange RangeArr[] = { R1, R2 }; + PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, 0, 0, RangeArr, 2); + return true; +} + +bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg, + SourceRange R1, SourceRange R2) { + SourceRange RangeArr[] = { R1, R2 }; + PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, &Msg, 1, RangeArr, 2); + return true; +} + +bool Sema::Diag(SourceLocation Range, unsigned DiagID, const std::string &Msg1, + const std::string &Msg2, SourceRange R1, SourceRange R2) { + std::string MsgArr[] = { Msg1, Msg2 }; + SourceRange RangeArr[] = { R1, R2 }; + PP.getDiagnostics().Report(PP.getFullLoc(Range),DiagID, MsgArr,2,RangeArr, 2); + return true; +} + +const LangOptions &Sema::getLangOptions() const { + return PP.getLangOptions(); +} |