2007-07-11 21:01:13 +04:00
|
|
|
//===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-29 22:59:25 +03:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2007-07-11 21:01:13 +04:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// 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"
|
2008-08-11 09:35:13 +04:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2008-08-11 08:54:23 +04:00
|
|
|
#include "clang/AST/Expr.h"
|
2007-07-11 21:01:13 +04:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
|
|
|
#include "clang/Basic/Diagnostic.h"
|
2007-08-11 00:18:51 +04:00
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
using namespace clang;
|
|
|
|
|
2008-08-24 02:20:38 +04:00
|
|
|
static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name)
|
|
|
|
{
|
|
|
|
if (C.getLangOptions().CPlusPlus)
|
|
|
|
return CXXRecordDecl::Create(C, TagDecl::TK_struct,
|
|
|
|
C.getTranslationUnitDecl(),
|
2008-09-05 05:34:33 +04:00
|
|
|
SourceLocation(), &C.Idents.get(Name));
|
2008-08-24 02:20:38 +04:00
|
|
|
else
|
|
|
|
return RecordDecl::Create(C, TagDecl::TK_struct,
|
|
|
|
C.getTranslationUnitDecl(),
|
2008-09-05 05:34:33 +04:00
|
|
|
SourceLocation(), &C.Idents.get(Name));
|
2008-08-24 02:20:38 +04:00
|
|
|
}
|
|
|
|
|
2007-10-31 21:42:27 +03:00
|
|
|
void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
|
|
|
|
TUScope = S;
|
2008-11-08 20:17:31 +03:00
|
|
|
PushDeclContext(Context.getTranslationUnitDecl());
|
2008-02-06 03:46:58 +03:00
|
|
|
if (!PP.getLangOptions().ObjC1) return;
|
|
|
|
|
2008-02-24 19:25:02 +03:00
|
|
|
// Synthesize "typedef struct objc_selector *SEL;"
|
2008-08-24 02:20:38 +04:00
|
|
|
RecordDecl *SelTag = CreateStructDecl(Context, "objc_selector");
|
2008-04-12 04:47:19 +04:00
|
|
|
PushOnScopeChains(SelTag, TUScope);
|
2008-02-24 19:25:02 +03:00
|
|
|
|
|
|
|
QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag));
|
2008-04-04 10:12:32 +04:00
|
|
|
TypedefDecl *SelTypedef = TypedefDecl::Create(Context, CurContext,
|
|
|
|
SourceLocation(),
|
2008-03-15 09:12:44 +03:00
|
|
|
&Context.Idents.get("SEL"),
|
2008-03-16 00:32:50 +03:00
|
|
|
SelT, 0);
|
2008-04-12 04:47:19 +04:00
|
|
|
PushOnScopeChains(SelTypedef, TUScope);
|
2008-02-24 19:25:02 +03:00
|
|
|
Context.setObjCSelType(SelTypedef);
|
2008-06-22 00:20:39 +04:00
|
|
|
|
2008-06-22 02:44:51 +04:00
|
|
|
// FIXME: Make sure these don't leak!
|
2008-08-24 02:20:38 +04:00
|
|
|
RecordDecl *ClassTag = CreateStructDecl(Context, "objc_class");
|
2008-06-22 00:20:39 +04:00
|
|
|
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 =
|
2008-07-21 11:06:49 +04:00
|
|
|
ObjCInterfaceDecl::Create(Context, SourceLocation(),
|
2008-06-22 00:20:39 +04:00
|
|
|
&Context.Idents.get("Protocol"),
|
|
|
|
SourceLocation(), true);
|
|
|
|
Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
|
|
|
|
PushOnScopeChains(ProtocolDecl, TUScope);
|
|
|
|
|
|
|
|
// Synthesize "typedef struct objc_object { Class isa; } *id;"
|
2008-08-24 02:20:38 +04:00
|
|
|
RecordDecl *ObjectTag = CreateStructDecl(Context, "objc_object");
|
|
|
|
|
2008-06-22 00:20:39 +04:00
|
|
|
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);
|
2007-10-17 00:40:23 +04:00
|
|
|
}
|
2007-10-11 01:53:07 +04:00
|
|
|
|
2008-02-06 03:46:58 +03:00
|
|
|
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer)
|
2008-11-08 20:17:31 +03:00
|
|
|
: PP(pp), Context(ctxt), Consumer(consumer), CurContext(0),PreDeclaratorDC(0),
|
|
|
|
CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()) {
|
2007-08-11 00:18:51 +04:00
|
|
|
|
|
|
|
// Get IdentifierInfo objects for known functions for which we
|
|
|
|
// do extra checking.
|
2008-02-06 03:46:58 +03:00
|
|
|
IdentifierTable &IT = PP.getIdentifierTable();
|
2007-08-11 00:18:51 +04:00
|
|
|
|
2008-10-02 22:44:07 +04:00
|
|
|
KnownFunctionIDs[id_printf] = &IT.get("printf");
|
|
|
|
KnownFunctionIDs[id_fprintf] = &IT.get("fprintf");
|
|
|
|
KnownFunctionIDs[id_sprintf] = &IT.get("sprintf");
|
|
|
|
KnownFunctionIDs[id_sprintf_chk] = &IT.get("__builtin___sprintf_chk");
|
|
|
|
KnownFunctionIDs[id_snprintf] = &IT.get("snprintf");
|
|
|
|
KnownFunctionIDs[id_snprintf_chk] = &IT.get("__builtin___snprintf_chk");
|
|
|
|
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_vsprintf_chk] = &IT.get("__builtin___vsprintf_chk");
|
|
|
|
KnownFunctionIDs[id_vsnprintf] = &IT.get("vsnprintf");
|
|
|
|
KnownFunctionIDs[id_vsnprintf_chk] = &IT.get("__builtin___vsnprintf_chk");
|
|
|
|
KnownFunctionIDs[id_vprintf] = &IT.get("vprintf");
|
2007-10-31 21:42:27 +03:00
|
|
|
|
2008-08-15 02:04:54 +04:00
|
|
|
SuperID = &IT.get("super");
|
|
|
|
|
2008-09-09 18:32:20 +04:00
|
|
|
// ObjC builtin typedef names.
|
|
|
|
Ident_id = &IT.get("id");
|
|
|
|
Ident_Class = &IT.get("Class");
|
|
|
|
Ident_SEL = &IT.get("SEL");
|
|
|
|
Ident_Protocol = &IT.get("Protocol");
|
|
|
|
|
2008-11-11 14:37:55 +03:00
|
|
|
Ident_StdNs = &IT.get("std");
|
|
|
|
Ident_TypeInfo = 0;
|
|
|
|
StdNamespace = 0;
|
|
|
|
|
2007-10-11 01:53:07 +04:00
|
|
|
TUScope = 0;
|
2008-07-01 14:37:29 +04:00
|
|
|
if (getLangOptions().CPlusPlus)
|
|
|
|
FieldCollector.reset(new CXXFieldCollector());
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
|
|
|
|
2008-01-16 22:17:22 +03:00
|
|
|
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
|
|
|
|
/// If there is already an implicit cast, merge into the existing one.
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59148 91177308-0d34-0410-b5e6-96231b3b80d8
2008-11-12 20:17:38 +03:00
|
|
|
/// If isLvalue, the result of the cast is an lvalue.
|
|
|
|
void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, bool isLvalue) {
|
2008-09-04 12:38:01 +04:00
|
|
|
QualType ExprTy = Context.getCanonicalType(Expr->getType());
|
|
|
|
QualType TypeTy = Context.getCanonicalType(Ty);
|
|
|
|
|
|
|
|
if (ExprTy == TypeTy)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (Expr->getType().getTypePtr()->isPointerType() &&
|
|
|
|
Ty.getTypePtr()->isPointerType()) {
|
|
|
|
QualType ExprBaseType =
|
|
|
|
cast<PointerType>(ExprTy.getUnqualifiedType())->getPointeeType();
|
|
|
|
QualType BaseType =
|
|
|
|
cast<PointerType>(TypeTy.getUnqualifiedType())->getPointeeType();
|
|
|
|
if (ExprBaseType.getAddressSpace() != BaseType.getAddressSpace()) {
|
|
|
|
Diag(Expr->getExprLoc(), diag::err_implicit_pointer_address_space_cast,
|
|
|
|
Expr->getSourceRange());
|
|
|
|
}
|
|
|
|
}
|
2008-01-16 22:17:22 +03:00
|
|
|
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59148 91177308-0d34-0410-b5e6-96231b3b80d8
2008-11-12 20:17:38 +03:00
|
|
|
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
|
2008-09-04 12:38:01 +04:00
|
|
|
ImpCast->setType(Ty);
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59148 91177308-0d34-0410-b5e6-96231b3b80d8
2008-11-12 20:17:38 +03:00
|
|
|
ImpCast->setLvalueCast(isLvalue);
|
|
|
|
} else
|
|
|
|
Expr = new ImplicitCastExpr(Ty, Expr, isLvalue);
|
2008-01-16 22:17:22 +03:00
|
|
|
}
|
|
|
|
|
2007-08-31 08:53:24 +04:00
|
|
|
void Sema::DeleteExpr(ExprTy *E) {
|
|
|
|
delete static_cast<Expr*>(E);
|
|
|
|
}
|
|
|
|
void Sema::DeleteStmt(StmtTy *S) {
|
|
|
|
delete static_cast<Stmt*>(S);
|
|
|
|
}
|
|
|
|
|
2008-08-23 07:19:52 +04:00
|
|
|
/// ActOnEndOfTranslationUnit - This is called at the very end of the
|
|
|
|
/// translation unit when EOF is reached and all but the top-level scope is
|
|
|
|
/// popped.
|
|
|
|
void Sema::ActOnEndOfTranslationUnit() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Helper functions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
bool Sema::Diag(SourceLocation Loc, unsigned DiagID) {
|
2007-12-13 01:39:36 +03:00
|
|
|
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID);
|
2007-07-11 21:01:13 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg) {
|
2008-11-18 07:56:44 +03:00
|
|
|
const std::string *Strs[] = { &Msg };
|
|
|
|
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, Strs, 1);
|
2007-07-11 21:01:13 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1,
|
|
|
|
const std::string &Msg2) {
|
2008-11-18 07:56:44 +03:00
|
|
|
const std::string *MsgArr[] = { &Msg1, &Msg2 };
|
2007-12-13 01:39:36 +03:00
|
|
|
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, MsgArr, 2);
|
2007-07-11 21:01:13 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-08-24 17:14:02 +04:00
|
|
|
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const SourceRange& Range) {
|
2007-12-13 01:39:36 +03:00
|
|
|
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, 0, 0, &Range,1);
|
2007-07-11 21:01:13 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
|
2008-08-24 17:14:02 +04:00
|
|
|
const SourceRange& Range) {
|
2008-11-18 07:56:44 +03:00
|
|
|
const std::string *Strs[] = { &Msg };
|
|
|
|
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, Strs, 1, &Range,1);
|
2007-07-11 21:01:13 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1,
|
2008-08-24 17:14:02 +04:00
|
|
|
const std::string &Msg2, const SourceRange& Range) {
|
2008-11-18 07:56:44 +03:00
|
|
|
const std::string *MsgArr[] = { &Msg1, &Msg2 };
|
2007-12-13 01:39:36 +03:00
|
|
|
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, MsgArr, 2, &Range, 1);
|
2007-07-11 21:01:13 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-01-04 02:38:43 +03:00
|
|
|
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1,
|
|
|
|
const std::string &Msg2, const std::string &Msg3,
|
2008-11-18 07:56:44 +03:00
|
|
|
const SourceRange &R1) {
|
|
|
|
const std::string *MsgArr[] = { &Msg1, &Msg2, &Msg3 };
|
2008-01-04 02:38:43 +03:00
|
|
|
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, MsgArr, 3, &R1, 1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
bool Sema::Diag(SourceLocation Loc, unsigned DiagID,
|
2008-08-24 17:14:02 +04:00
|
|
|
const SourceRange& R1, const SourceRange& R2) {
|
2007-07-11 21:01:13 +04:00
|
|
|
SourceRange RangeArr[] = { R1, R2 };
|
2007-12-13 01:39:36 +03:00
|
|
|
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, 0, 0, RangeArr, 2);
|
2007-07-11 21:01:13 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
|
2008-08-24 17:14:02 +04:00
|
|
|
const SourceRange& R1, const SourceRange& R2) {
|
2007-07-11 21:01:13 +04:00
|
|
|
SourceRange RangeArr[] = { R1, R2 };
|
2008-11-18 07:56:44 +03:00
|
|
|
const std::string *Strs[] = { &Msg };
|
|
|
|
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, Strs, 1, RangeArr, 2);
|
2007-07-11 21:01:13 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sema::Diag(SourceLocation Range, unsigned DiagID, const std::string &Msg1,
|
2008-08-24 17:14:02 +04:00
|
|
|
const std::string &Msg2, const SourceRange& R1,
|
|
|
|
const SourceRange& R2) {
|
2008-11-18 07:56:44 +03:00
|
|
|
const std::string *MsgArr[] = { &Msg1, &Msg2 };
|
2007-07-11 21:01:13 +04:00
|
|
|
SourceRange RangeArr[] = { R1, R2 };
|
2007-12-13 01:39:36 +03:00
|
|
|
PP.getDiagnostics().Report(PP.getFullLoc(Range),DiagID, MsgArr,2,RangeArr, 2);
|
2007-07-11 21:01:13 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const LangOptions &Sema::getLangOptions() const {
|
|
|
|
return PP.getLangOptions();
|
|
|
|
}
|
2008-08-11 09:35:13 +04:00
|
|
|
|
|
|
|
ObjCMethodDecl *Sema::getCurMethodDecl() {
|
2008-11-17 19:28:52 +03:00
|
|
|
DeclContext *DC = CurContext;
|
|
|
|
while (isa<BlockDecl>(DC))
|
|
|
|
DC = DC->getParent();
|
|
|
|
return dyn_cast<ObjCMethodDecl>(DC);
|
2008-08-11 09:35:13 +04:00
|
|
|
}
|