2006-11-10 12:58:55 +08:00
|
|
|
//===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===//
|
2006-08-17 13:51:27 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 03:59:25 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2006-08-17 13:51:27 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2006-11-10 12:58:55 +08:00
|
|
|
// This file implements the actions class which performs semantic analysis and
|
|
|
|
// builds an AST out of a parse stream.
|
2006-08-17 13:51:27 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2006-11-10 12:58:55 +08:00
|
|
|
#include "Sema.h"
|
2006-11-10 14:20:45 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2008-08-11 13:35:13 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2008-08-11 12:54:23 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2006-10-06 13:22:26 +08:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2006-08-18 13:17:52 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2008-11-23 17:13:29 +08:00
|
|
|
/// ConvertQualTypeToStringFn - This function is used to pretty print the
|
|
|
|
/// specified QualType as a string in diagnostics.
|
2008-11-24 04:28:15 +08:00
|
|
|
static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
|
2008-11-24 11:33:13 +08:00
|
|
|
const char *Modifier, unsigned ModLen,
|
2008-11-23 17:13:29 +08:00
|
|
|
const char *Argument, unsigned ArgLen,
|
|
|
|
llvm::SmallVectorImpl<char> &Output) {
|
2008-11-23 17:21:17 +08:00
|
|
|
|
2008-11-24 04:28:15 +08:00
|
|
|
std::string S;
|
|
|
|
if (Kind == Diagnostic::ak_qualtype) {
|
|
|
|
QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));
|
2008-11-24 11:33:13 +08:00
|
|
|
|
2008-11-24 04:28:15 +08:00
|
|
|
// FIXME: Playing with std::string is really slow.
|
|
|
|
S = Ty.getAsString();
|
2008-11-24 11:33:13 +08:00
|
|
|
|
|
|
|
assert(ModLen == 0 && ArgLen == 0 &&
|
|
|
|
"Invalid modifier for QualType argument");
|
|
|
|
|
2009-02-05 01:27:36 +08:00
|
|
|
} else if (Kind == Diagnostic::ak_declarationname) {
|
2008-11-24 04:28:15 +08:00
|
|
|
|
|
|
|
DeclarationName N = DeclarationName::getFromOpaqueInteger(Val);
|
|
|
|
S = N.getAsString();
|
2008-11-24 11:33:13 +08:00
|
|
|
|
|
|
|
if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0)
|
|
|
|
S = '+' + S;
|
|
|
|
else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12) && ArgLen==0)
|
|
|
|
S = '-' + S;
|
|
|
|
else
|
|
|
|
assert(ModLen == 0 && ArgLen == 0 &&
|
|
|
|
"Invalid modifier for DeclarationName argument");
|
2009-02-05 01:27:36 +08:00
|
|
|
} else {
|
|
|
|
assert(Kind == Diagnostic::ak_nameddecl);
|
2009-02-05 06:46:25 +08:00
|
|
|
if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0)
|
|
|
|
S = reinterpret_cast<NamedDecl*>(Val)->getQualifiedNameAsString();
|
|
|
|
else {
|
|
|
|
assert(ModLen == 0 && ArgLen == 0 &&
|
2009-02-05 01:27:36 +08:00
|
|
|
"Invalid modifier for NamedDecl* argument");
|
2009-02-05 06:46:25 +08:00
|
|
|
S = reinterpret_cast<NamedDecl*>(Val)->getNameAsString();
|
|
|
|
}
|
2008-11-24 04:28:15 +08:00
|
|
|
}
|
2008-11-23 17:13:29 +08:00
|
|
|
Output.append(S.begin(), S.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
This reworks some of the Diagnostic interfaces a bit to change how diagnostics
are formed. In particular, a diagnostic with all its strings and ranges is now
packaged up and sent to DiagnosticClients as a DiagnosticInfo instead of as a
ton of random stuff. This has the benefit of simplifying the interface, making
it more extensible, and allowing us to do more checking for things like access
past the end of the various arrays passed in.
In addition to introducing DiagnosticInfo, this also substantially changes how
Diagnostic::Report works. Instead of being passed in all of the info required
to issue a diagnostic, Report now takes only the required info (a location and
ID) and returns a fresh DiagnosticInfo *by value*. The caller is then free to
stuff strings and ranges into the DiagnosticInfo with the << operator. When
the dtor runs on the DiagnosticInfo object (which should happen at the end of
the statement), the diagnostic is actually emitted with all of the accumulated
information. This is a somewhat tricky dance, but it means that the
accumulated DiagnosticInfo is allowed to keep pointers to other expression
temporaries without those pointers getting invalidated.
This is just the minimal change to get this stuff working, but this will allow
us to eliminate the zillions of variant "Diag" methods scattered throughout
(e.g.) sema. For example, instead of calling:
Diag(BuiltinLoc, diag::err_overload_no_match, typeNames,
SourceRange(BuiltinLoc, RParenLoc));
We will soon be able to just do:
Diag(BuiltinLoc, diag::err_overload_no_match)
<< typeNames << SourceRange(BuiltinLoc, RParenLoc));
This scales better to support arbitrary types being passed in (not just
strings) in a type-safe way. Go operator overloading?!
llvm-svn: 59502
2008-11-18 15:04:44 +08:00
|
|
|
static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name) {
|
2008-08-24 06:20:38 +08:00
|
|
|
if (C.getLangOptions().CPlusPlus)
|
|
|
|
return CXXRecordDecl::Create(C, TagDecl::TK_struct,
|
|
|
|
C.getTranslationUnitDecl(),
|
2008-09-05 09:34:33 +08:00
|
|
|
SourceLocation(), &C.Idents.get(Name));
|
2008-11-19 13:08:23 +08:00
|
|
|
|
|
|
|
return RecordDecl::Create(C, TagDecl::TK_struct,
|
|
|
|
C.getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), &C.Idents.get(Name));
|
2008-08-24 06:20:38 +08:00
|
|
|
}
|
|
|
|
|
2007-11-01 02:42:27 +08:00
|
|
|
void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
|
|
|
|
TUScope = S;
|
2008-12-12 00:49:14 +08:00
|
|
|
PushDeclContext(S, Context.getTranslationUnitDecl());
|
2008-02-06 08:46:58 +08:00
|
|
|
if (!PP.getLangOptions().ObjC1) return;
|
|
|
|
|
2008-02-25 00:25:02 +08:00
|
|
|
// Synthesize "typedef struct objc_selector *SEL;"
|
2008-08-24 06:20:38 +08:00
|
|
|
RecordDecl *SelTag = CreateStructDecl(Context, "objc_selector");
|
2008-04-12 08:47:19 +08:00
|
|
|
PushOnScopeChains(SelTag, TUScope);
|
2008-02-25 00:25:02 +08:00
|
|
|
|
|
|
|
QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag));
|
2008-04-04 14:12:32 +08:00
|
|
|
TypedefDecl *SelTypedef = TypedefDecl::Create(Context, CurContext,
|
|
|
|
SourceLocation(),
|
2008-03-15 14:12:44 +08:00
|
|
|
&Context.Idents.get("SEL"),
|
2009-01-20 09:17:11 +08:00
|
|
|
SelT);
|
2008-04-12 08:47:19 +08:00
|
|
|
PushOnScopeChains(SelTypedef, TUScope);
|
2008-02-25 00:25:02 +08:00
|
|
|
Context.setObjCSelType(SelTypedef);
|
2008-06-22 04:20:39 +08:00
|
|
|
|
2008-06-22 06:44:51 +08:00
|
|
|
// FIXME: Make sure these don't leak!
|
2008-08-24 06:20:38 +08:00
|
|
|
RecordDecl *ClassTag = CreateStructDecl(Context, "objc_class");
|
2008-06-22 04:20:39 +08:00
|
|
|
QualType ClassT = Context.getPointerType(Context.getTagDeclType(ClassTag));
|
|
|
|
TypedefDecl *ClassTypedef =
|
|
|
|
TypedefDecl::Create(Context, CurContext, SourceLocation(),
|
2009-01-20 09:17:11 +08:00
|
|
|
&Context.Idents.get("Class"), ClassT);
|
2008-06-22 04:20:39 +08:00
|
|
|
PushOnScopeChains(ClassTag, TUScope);
|
|
|
|
PushOnScopeChains(ClassTypedef, TUScope);
|
|
|
|
Context.setObjCClassType(ClassTypedef);
|
|
|
|
// Synthesize "@class Protocol;
|
|
|
|
ObjCInterfaceDecl *ProtocolDecl =
|
2009-01-09 08:49:46 +08:00
|
|
|
ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
|
2008-06-22 04:20:39 +08: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 06:20:38 +08:00
|
|
|
RecordDecl *ObjectTag = CreateStructDecl(Context, "objc_object");
|
|
|
|
|
2008-06-22 04:20:39 +08:00
|
|
|
QualType ObjT = Context.getPointerType(Context.getTagDeclType(ObjectTag));
|
|
|
|
PushOnScopeChains(ObjectTag, TUScope);
|
|
|
|
TypedefDecl *IdTypedef = TypedefDecl::Create(Context, CurContext,
|
|
|
|
SourceLocation(),
|
|
|
|
&Context.Idents.get("id"),
|
2009-01-20 09:17:11 +08:00
|
|
|
ObjT);
|
2008-06-22 04:20:39 +08:00
|
|
|
PushOnScopeChains(IdTypedef, TUScope);
|
|
|
|
Context.setObjCIdType(IdTypedef);
|
2007-10-17 04:40:23 +08:00
|
|
|
}
|
2007-10-11 05:53:07 +08:00
|
|
|
|
2008-02-06 08:46:58 +08:00
|
|
|
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer)
|
2009-01-23 03:21:44 +08:00
|
|
|
: LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
|
|
|
|
Diags(PP.getDiagnostics()),
|
2008-11-22 16:28:49 +08:00
|
|
|
SourceMgr(PP.getSourceManager()), CurContext(0), PreDeclaratorDC(0),
|
2008-12-04 04:26:15 +08:00
|
|
|
CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()),
|
|
|
|
GlobalNewDeleteDeclared(false) {
|
2007-08-11 04:18:51 +08:00
|
|
|
|
|
|
|
// Get IdentifierInfo objects for known functions for which we
|
|
|
|
// do extra checking.
|
2008-02-06 08:46:58 +08:00
|
|
|
IdentifierTable &IT = PP.getIdentifierTable();
|
2007-08-11 04:18:51 +08:00
|
|
|
|
2008-10-03 02:44:07 +08:00
|
|
|
KnownFunctionIDs[id_NSLog] = &IT.get("NSLog");
|
2009-02-15 02:57:46 +08:00
|
|
|
KnownFunctionIDs[id_NSLogv] = &IT.get("NSLogv");
|
2009-02-14 08:32:47 +08:00
|
|
|
KnownFunctionIDs[id_asprintf] = &IT.get("asprintf");
|
2008-10-03 02:44:07 +08:00
|
|
|
KnownFunctionIDs[id_vasprintf] = &IT.get("vasprintf");
|
2007-11-01 02:42:27 +08:00
|
|
|
|
2008-11-11 19:37:55 +08:00
|
|
|
StdNamespace = 0;
|
2007-10-11 05:53:07 +08:00
|
|
|
TUScope = 0;
|
2008-07-01 18:37:29 +08:00
|
|
|
if (getLangOptions().CPlusPlus)
|
|
|
|
FieldCollector.reset(new CXXFieldCollector());
|
2008-11-23 17:13:29 +08:00
|
|
|
|
|
|
|
// Tell diagnostics how to render things from the AST library.
|
2008-11-23 17:21:17 +08:00
|
|
|
PP.getDiagnostics().SetArgToStringFn(ConvertArgToStringFn);
|
2007-02-28 09:22:02 +08:00
|
|
|
}
|
2006-11-10 14:20:45 +08:00
|
|
|
|
2008-01-17 03:17:22 +08: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.
|
2009-01-18 14:42:49 +08:00
|
|
|
/// If isLvalue, the result of the cast is an lvalue.
|
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.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, bool isLvalue) {
|
2008-09-04 16:38:01 +08: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()) {
|
2008-11-19 13:27:50 +08:00
|
|
|
Diag(Expr->getExprLoc(), diag::err_implicit_pointer_address_space_cast)
|
|
|
|
<< Expr->getSourceRange();
|
2008-09-04 16:38:01 +08:00
|
|
|
}
|
|
|
|
}
|
2008-01-17 03:17:22 +08: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.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
|
2008-09-04 16:38:01 +08: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.
llvm-svn: 59148
2008-11-13 01:17:38 +08:00
|
|
|
ImpCast->setLvalueCast(isLvalue);
|
|
|
|
} else
|
2009-02-07 09:47:29 +08:00
|
|
|
Expr = new (Context) ImplicitCastExpr(Ty, Expr, isLvalue);
|
2008-01-17 03:17:22 +08:00
|
|
|
}
|
|
|
|
|
2007-08-31 12:53:24 +08:00
|
|
|
void Sema::DeleteExpr(ExprTy *E) {
|
2009-01-22 08:58:24 +08:00
|
|
|
if (E) static_cast<Expr*>(E)->Destroy(Context);
|
2007-08-31 12:53:24 +08:00
|
|
|
}
|
|
|
|
void Sema::DeleteStmt(StmtTy *S) {
|
2009-01-22 08:58:24 +08:00
|
|
|
if (S) static_cast<Stmt*>(S)->Destroy(Context);
|
2007-08-31 12:53:24 +08:00
|
|
|
}
|
|
|
|
|
2008-08-23 11:19:52 +08: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() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-10 13:17:58 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Helper functions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-12-05 07:50:19 +08:00
|
|
|
/// getCurFunctionDecl - If inside of a function body, this returns a pointer
|
|
|
|
/// to the function decl for the function being parsed. If we're currently
|
|
|
|
/// in a 'block', this returns the containing context.
|
|
|
|
FunctionDecl *Sema::getCurFunctionDecl() {
|
|
|
|
DeclContext *DC = CurContext;
|
|
|
|
while (isa<BlockDecl>(DC))
|
|
|
|
DC = DC->getParent();
|
|
|
|
return dyn_cast<FunctionDecl>(DC);
|
|
|
|
}
|
|
|
|
|
2008-08-11 13:35:13 +08:00
|
|
|
ObjCMethodDecl *Sema::getCurMethodDecl() {
|
2008-11-18 00:28:52 +08:00
|
|
|
DeclContext *DC = CurContext;
|
|
|
|
while (isa<BlockDecl>(DC))
|
|
|
|
DC = DC->getParent();
|
|
|
|
return dyn_cast<ObjCMethodDecl>(DC);
|
2008-08-11 13:35:13 +08:00
|
|
|
}
|
2008-12-05 07:50:19 +08:00
|
|
|
|
|
|
|
NamedDecl *Sema::getCurFunctionOrMethodDecl() {
|
|
|
|
DeclContext *DC = CurContext;
|
|
|
|
while (isa<BlockDecl>(DC))
|
|
|
|
DC = DC->getParent();
|
|
|
|
if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC))
|
2009-01-20 09:17:11 +08:00
|
|
|
return cast<NamedDecl>(DC);
|
2008-12-05 07:50:19 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|