Sema.cpp revision b6ccaac65ca72f72954eb3893bbd940bedd23f00
1//===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the actions class which performs semantic analysis and
11// builds an AST out of a parse stream.
12//
13//===----------------------------------------------------------------------===//
14
15#include "Sema.h"
16#include "clang/AST/ASTContext.h"
17#include "clang/Lex/Preprocessor.h"
18#include "clang/Basic/Diagnostic.h"
19#include "clang/Parse/Scope.h"
20
21using namespace clang;
22
23bool Sema::isBuiltinObjCType(TypedefDecl *TD) {
24  const char *typeName = TD->getIdentifier()->getName();
25  return strcmp(typeName, "id") == 0 || strcmp(typeName, "Class") == 0 ||
26         strcmp(typeName, "SEL") == 0 || strcmp(typeName, "Protocol") == 0;
27}
28
29void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
30  TUScope = S;
31  CurContext = Context.getTranslationUnitDecl();
32  if (!PP.getLangOptions().ObjC1) return;
33
34  // Synthesize "typedef struct objc_selector *SEL;"
35  RecordDecl *SelTag = RecordDecl::Create(Context, TagDecl::TK_struct,
36                                          CurContext,
37                                          SourceLocation(),
38                                          &Context.Idents.get("objc_selector"),
39                                          0);
40  PushOnScopeChains(SelTag, TUScope);
41
42  QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag));
43  TypedefDecl *SelTypedef = TypedefDecl::Create(Context, CurContext,
44                                                SourceLocation(),
45                                                &Context.Idents.get("SEL"),
46                                                SelT, 0);
47  PushOnScopeChains(SelTypedef, TUScope);
48  Context.setObjCSelType(SelTypedef);
49
50  // FIXME: Make sure these don't leak!
51  RecordDecl *ClassTag = RecordDecl::Create(Context, TagDecl::TK_struct,
52                                            CurContext,
53                                            SourceLocation(),
54                                            &Context.Idents.get("objc_class"),
55                                            0);
56  QualType ClassT = Context.getPointerType(Context.getTagDeclType(ClassTag));
57  TypedefDecl *ClassTypedef =
58    TypedefDecl::Create(Context, CurContext, SourceLocation(),
59                        &Context.Idents.get("Class"), ClassT, 0);
60  PushOnScopeChains(ClassTag, TUScope);
61  PushOnScopeChains(ClassTypedef, TUScope);
62  Context.setObjCClassType(ClassTypedef);
63  // Synthesize "@class Protocol;
64  ObjCInterfaceDecl *ProtocolDecl =
65    ObjCInterfaceDecl::Create(Context, SourceLocation(),
66                              &Context.Idents.get("Protocol"),
67                              SourceLocation(), true);
68  Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
69  PushOnScopeChains(ProtocolDecl, TUScope);
70
71  // Synthesize "typedef struct objc_object { Class isa; } *id;"
72  RecordDecl *ObjectTag =
73    RecordDecl::Create(Context, TagDecl::TK_struct, CurContext,
74                       SourceLocation(),
75                       &Context.Idents.get("objc_object"), 0);
76  QualType ObjT = Context.getPointerType(Context.getTagDeclType(ObjectTag));
77  PushOnScopeChains(ObjectTag, TUScope);
78  TypedefDecl *IdTypedef = TypedefDecl::Create(Context, CurContext,
79                                               SourceLocation(),
80                                               &Context.Idents.get("id"),
81                                               ObjT, 0);
82  PushOnScopeChains(IdTypedef, TUScope);
83  Context.setObjCIdType(IdTypedef);
84}
85
86Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer)
87  : PP(pp), Context(ctxt), Consumer(consumer), CurContext(0) {
88
89  // Get IdentifierInfo objects for known functions for which we
90  // do extra checking.
91  IdentifierTable &IT = PP.getIdentifierTable();
92
93  KnownFunctionIDs[id_printf]    = &IT.get("printf");
94  KnownFunctionIDs[id_fprintf]   = &IT.get("fprintf");
95  KnownFunctionIDs[id_sprintf]   = &IT.get("sprintf");
96  KnownFunctionIDs[id_snprintf]  = &IT.get("snprintf");
97  KnownFunctionIDs[id_asprintf]  = &IT.get("asprintf");
98  KnownFunctionIDs[id_NSLog]     = &IT.get("NSLog");
99  KnownFunctionIDs[id_vsnprintf] = &IT.get("vsnprintf");
100  KnownFunctionIDs[id_vasprintf] = &IT.get("vasprintf");
101  KnownFunctionIDs[id_vfprintf]  = &IT.get("vfprintf");
102  KnownFunctionIDs[id_vsprintf]  = &IT.get("vsprintf");
103  KnownFunctionIDs[id_vprintf]   = &IT.get("vprintf");
104
105  TUScope = 0;
106  if (getLangOptions().CPlusPlus)
107    FieldCollector.reset(new CXXFieldCollector());
108}
109
110/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
111/// If there is already an implicit cast, merge into the existing one.
112void Sema::ImpCastExprToType(Expr *&Expr, QualType Type) {
113  if (Expr->getType().getCanonicalType() == Type.getCanonicalType()) return;
114
115  if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr))
116    ImpCast->setType(Type);
117  else
118    Expr = new ImplicitCastExpr(Type, Expr);
119}
120
121
122
123void Sema::DeleteExpr(ExprTy *E) {
124  delete static_cast<Expr*>(E);
125}
126void Sema::DeleteStmt(StmtTy *S) {
127  delete static_cast<Stmt*>(S);
128}
129
130//===----------------------------------------------------------------------===//
131// Helper functions.
132//===----------------------------------------------------------------------===//
133
134bool Sema::Diag(SourceLocation Loc, unsigned DiagID) {
135  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID);
136  return true;
137}
138
139bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg) {
140  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID,  &Msg, 1);
141  return true;
142}
143
144bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1,
145                const std::string &Msg2) {
146  std::string MsgArr[] = { Msg1, Msg2 };
147  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID,  MsgArr, 2);
148  return true;
149}
150
151bool Sema::Diag(SourceLocation Loc, unsigned DiagID, SourceRange Range) {
152  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, 0, 0, &Range,1);
153  return true;
154}
155
156bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
157                SourceRange Range) {
158  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, &Msg, 1, &Range,1);
159  return true;
160}
161
162bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1,
163                const std::string &Msg2, SourceRange Range) {
164  std::string MsgArr[] = { Msg1, Msg2 };
165  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, MsgArr, 2, &Range, 1);
166  return true;
167}
168
169bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1,
170                const std::string &Msg2, const std::string &Msg3,
171                SourceRange R1) {
172  std::string MsgArr[] = { Msg1, Msg2, Msg3 };
173  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, MsgArr, 3, &R1, 1);
174  return true;
175}
176
177bool Sema::Diag(SourceLocation Loc, unsigned DiagID,
178                SourceRange R1, SourceRange R2) {
179  SourceRange RangeArr[] = { R1, R2 };
180  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, 0, 0, RangeArr, 2);
181  return true;
182}
183
184bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
185                SourceRange R1, SourceRange R2) {
186  SourceRange RangeArr[] = { R1, R2 };
187  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID,  &Msg, 1, RangeArr, 2);
188  return true;
189}
190
191bool Sema::Diag(SourceLocation Range, unsigned DiagID, const std::string &Msg1,
192                const std::string &Msg2, SourceRange R1, SourceRange R2) {
193  std::string MsgArr[] = { Msg1, Msg2 };
194  SourceRange RangeArr[] = { R1, R2 };
195  PP.getDiagnostics().Report(PP.getFullLoc(Range),DiagID, MsgArr,2,RangeArr, 2);
196  return true;
197}
198
199const LangOptions &Sema::getLangOptions() const {
200  return PP.getLangOptions();
201}
202