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"
|
2009-07-30 11:15:39 +08:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2009-04-22 01:11:58 +08:00
|
|
|
#include "clang/AST/ASTConsumer.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"
|
2009-08-27 06:33:56 +08:00
|
|
|
#include "clang/Basic/PartialDiagnostic.h"
|
2009-04-30 14:18:40 +08:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
2006-08-18 13:17:52 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
/// ConvertQualTypeToStringFn - This function is used to pretty print the
|
2008-11-23 17:13:29 +08:00
|
|
|
/// specified QualType as a string in diagnostics.
|
2008-11-24 04:28:15 +08:00
|
|
|
static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
|
2009-02-20 07:45:49 +08:00
|
|
|
const char *Modifier, unsigned ModLen,
|
|
|
|
const char *Argument, unsigned ArgLen,
|
2009-02-20 07:53:20 +08:00
|
|
|
llvm::SmallVectorImpl<char> &Output,
|
|
|
|
void *Cookie) {
|
|
|
|
ASTContext &Context = *static_cast<ASTContext*>(Cookie);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-24 04:28:15 +08:00
|
|
|
std::string S;
|
|
|
|
if (Kind == Diagnostic::ak_qualtype) {
|
2009-02-20 07:45:49 +08:00
|
|
|
assert(ModLen == 0 && ArgLen == 0 &&
|
|
|
|
"Invalid modifier for QualType argument");
|
|
|
|
|
2008-11-24 04:28:15 +08:00
|
|
|
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.
|
2009-05-30 04:38:28 +08:00
|
|
|
S = Ty.getAsString(Context.PrintingPolicy);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-20 07:45:49 +08:00
|
|
|
// If this is a sugared type (like a typedef, typeof, etc), then unwrap one
|
|
|
|
// level of the sugar so that the type is more obvious to the user.
|
Give Type::getDesugaredType a "for-display" mode that can apply more
heuristics to determine when it's useful to desugar a type for display
to the user. Introduce two C++-specific heuristics:
- For a qualified type (like "foo::bar"), only produce a new
desugred type if desugaring the qualified type ("bar", in this
case) produces something interesting. For example, if "foo::bar"
refers to a class named "bar", don't desugar. However, if
"foo::bar" refers to a typedef of something else, desugar to that
something else. This gives some useful desugaring such as
"foo::bar (aka 'int')".
- Don't desugar class template specialization types like
"basic_string<char>" down to their underlying "class
basic_string<char, char_traits<char>, allocator<char>>, etc.";
it's better just to leave such types alone.
Update diagnostics.html with some discussion and examples of type
preservation in C++, showing qualified names and class template
specialization types.
llvm-svn: 68207
2009-04-01 23:47:24 +08:00
|
|
|
QualType DesugaredTy = Ty->getDesugaredType(true);
|
2009-02-20 07:45:49 +08:00
|
|
|
DesugaredTy.setCVRQualifiers(DesugaredTy.getCVRQualifiers() |
|
|
|
|
Ty.getCVRQualifiers());
|
2008-11-24 11:33:13 +08:00
|
|
|
|
2009-02-20 07:45:49 +08:00
|
|
|
if (Ty != DesugaredTy &&
|
|
|
|
// If the desugared type is a vector type, we don't want to expand it,
|
|
|
|
// it will turn into an attribute mess. People want their "vec4".
|
|
|
|
!isa<VectorType>(DesugaredTy) &&
|
2009-09-05 14:31:47 +08:00
|
|
|
|
|
|
|
// Don't aka just because we saw an elaborated type.
|
|
|
|
(!isa<ElaboratedType>(Ty) ||
|
|
|
|
cast<ElaboratedType>(Ty)->getUnderlyingType() != DesugaredTy) &&
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-20 07:53:20 +08:00
|
|
|
// Don't desugar magic Objective-C types.
|
|
|
|
Ty.getUnqualifiedType() != Context.getObjCIdType() &&
|
2009-07-11 07:34:53 +08:00
|
|
|
Ty.getUnqualifiedType() != Context.getObjCClassType() &&
|
2009-02-20 07:53:20 +08:00
|
|
|
Ty.getUnqualifiedType() != Context.getObjCSelType() &&
|
|
|
|
Ty.getUnqualifiedType() != Context.getObjCProtoType() &&
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-20 07:53:20 +08:00
|
|
|
// Not va_list.
|
|
|
|
Ty.getUnqualifiedType() != Context.getBuiltinVaListType()) {
|
2009-02-20 07:45:49 +08:00
|
|
|
S = "'"+S+"' (aka '";
|
2009-06-03 10:06:50 +08:00
|
|
|
S += DesugaredTy.getAsString(Context.PrintingPolicy);
|
2009-02-20 07:45:49 +08:00
|
|
|
S += "')";
|
|
|
|
Output.append(S.begin(), S.end());
|
|
|
|
return;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-05 01:27:36 +08:00
|
|
|
} else if (Kind == Diagnostic::ak_declarationname) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-24 04:28:15 +08:00
|
|
|
DeclarationName N = DeclarationName::getFromOpaqueInteger(Val);
|
|
|
|
S = N.getAsString();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
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-08-26 08:04:55 +08:00
|
|
|
} else if (Kind == Diagnostic::ak_nameddecl) {
|
2009-09-11 14:45:03 +08:00
|
|
|
bool Qualified;
|
2009-02-05 06:46:25 +08:00
|
|
|
if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0)
|
2009-09-11 14:45:03 +08:00
|
|
|
Qualified = true;
|
2009-09-09 23:08:12 +08:00
|
|
|
else {
|
2009-02-05 06:46:25 +08:00
|
|
|
assert(ModLen == 0 && ArgLen == 0 &&
|
2009-02-05 01:27:36 +08:00
|
|
|
"Invalid modifier for NamedDecl* argument");
|
2009-09-11 14:45:03 +08:00
|
|
|
Qualified = false;
|
2009-02-05 06:46:25 +08:00
|
|
|
}
|
2009-09-11 14:45:03 +08:00
|
|
|
reinterpret_cast<NamedDecl*>(Val)->getNameForDiagnostic(S,
|
|
|
|
Context.PrintingPolicy,
|
|
|
|
Qualified);
|
2009-08-26 08:04:55 +08:00
|
|
|
} else {
|
|
|
|
llvm::raw_string_ostream OS(S);
|
|
|
|
assert(Kind == Diagnostic::ak_nestednamespec);
|
2009-09-09 23:08:12 +08:00
|
|
|
reinterpret_cast<NestedNameSpecifier*> (Val)->print(OS,
|
2009-08-26 08:04:55 +08:00
|
|
|
Context.PrintingPolicy);
|
2008-11-24 04:28:15 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-20 07:45:49 +08:00
|
|
|
Output.push_back('\'');
|
2008-11-23 17:13:29 +08:00
|
|
|
Output.append(S.begin(), S.end());
|
2009-02-20 07:45:49 +08:00
|
|
|
Output.push_back('\'');
|
2008-11-23 17:13:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
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)
|
2009-09-09 23:08:12 +08:00
|
|
|
return CXXRecordDecl::Create(C, TagDecl::TK_struct,
|
2008-08-24 06:20:38 +08:00
|
|
|
C.getTranslationUnitDecl(),
|
2008-09-05 09:34:33 +08:00
|
|
|
SourceLocation(), &C.Idents.get(Name));
|
2008-11-19 13:08:23 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
return RecordDecl::Create(C, TagDecl::TK_struct,
|
2008-11-19 13:08:23 +08:00
|
|
|
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());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-04-30 14:18:40 +08:00
|
|
|
if (PP.getTargetInfo().getPointerWidth(0) >= 64) {
|
|
|
|
// Install [u]int128_t for 64-bit targets.
|
|
|
|
PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
|
|
|
|
SourceLocation(),
|
|
|
|
&Context.Idents.get("__int128_t"),
|
|
|
|
Context.Int128Ty), TUScope);
|
|
|
|
PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
|
|
|
|
SourceLocation(),
|
|
|
|
&Context.Idents.get("__uint128_t"),
|
|
|
|
Context.UnsignedInt128Ty), TUScope);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
2008-02-06 08:46:58 +08:00
|
|
|
if (!PP.getLangOptions().ObjC1) return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-16 08:20:10 +08:00
|
|
|
// Built-in ObjC types may already be set by PCHReader (hence isNull checks).
|
2009-04-24 06:29:11 +08:00
|
|
|
if (Context.getObjCSelType().isNull()) {
|
|
|
|
// Synthesize "typedef struct objc_selector *SEL;"
|
|
|
|
RecordDecl *SelTag = CreateStructDecl(Context, "objc_selector");
|
|
|
|
PushOnScopeChains(SelTag, TUScope);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-04-24 06:29:11 +08:00
|
|
|
QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag));
|
|
|
|
TypedefDecl *SelTypedef = TypedefDecl::Create(Context, CurContext,
|
|
|
|
SourceLocation(),
|
|
|
|
&Context.Idents.get("SEL"),
|
|
|
|
SelT);
|
|
|
|
PushOnScopeChains(SelTypedef, TUScope);
|
|
|
|
Context.setObjCSelType(Context.getTypeDeclType(SelTypedef));
|
|
|
|
}
|
|
|
|
|
2008-06-22 04:20:39 +08:00
|
|
|
// Synthesize "@class Protocol;
|
2009-04-24 06:29:11 +08:00
|
|
|
if (Context.getObjCProtoType().isNull()) {
|
|
|
|
ObjCInterfaceDecl *ProtocolDecl =
|
|
|
|
ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
&Context.Idents.get("Protocol"),
|
2009-04-24 06:29:11 +08:00
|
|
|
SourceLocation(), true);
|
|
|
|
Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
|
|
|
|
PushOnScopeChains(ProtocolDecl, TUScope);
|
|
|
|
}
|
2009-07-16 02:40:39 +08:00
|
|
|
// Create the built-in typedef for 'id'.
|
2009-04-24 06:29:11 +08:00
|
|
|
if (Context.getObjCIdType().isNull()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
TypedefDecl *IdTypedef =
|
|
|
|
TypedefDecl::Create(
|
2009-07-16 02:40:39 +08:00
|
|
|
Context, CurContext, SourceLocation(), &Context.Idents.get("id"),
|
|
|
|
Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy)
|
|
|
|
);
|
2009-04-24 06:29:11 +08:00
|
|
|
PushOnScopeChains(IdTypedef, TUScope);
|
|
|
|
Context.setObjCIdType(Context.getTypeDeclType(IdTypedef));
|
2009-08-18 00:35:33 +08:00
|
|
|
Context.ObjCIdRedefinitionType = Context.getObjCIdType();
|
2009-04-24 06:29:11 +08:00
|
|
|
}
|
2009-07-16 02:40:39 +08:00
|
|
|
// Create the built-in typedef for 'Class'.
|
2009-07-11 07:34:53 +08:00
|
|
|
if (Context.getObjCClassType().isNull()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
TypedefDecl *ClassTypedef =
|
|
|
|
TypedefDecl::Create(
|
2009-07-16 02:40:39 +08:00
|
|
|
Context, CurContext, SourceLocation(), &Context.Idents.get("Class"),
|
|
|
|
Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy)
|
|
|
|
);
|
2009-07-11 07:34:53 +08:00
|
|
|
PushOnScopeChains(ClassTypedef, TUScope);
|
|
|
|
Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
|
2009-08-18 00:35:33 +08:00
|
|
|
Context.ObjCClassRedefinitionType = Context.getObjCClassType();
|
2009-07-11 07:34:53 +08:00
|
|
|
}
|
2007-10-17 04:40:23 +08:00
|
|
|
}
|
2007-10-11 05:53:07 +08:00
|
|
|
|
2009-04-15 00:27:31 +08:00
|
|
|
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
|
|
|
|
bool CompleteTranslationUnit)
|
2009-01-23 03:21:44 +08:00
|
|
|
: LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
|
2009-09-09 23:08:12 +08:00
|
|
|
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
|
2009-04-25 05:10:55 +08:00
|
|
|
ExternalSource(0), CurContext(0), PreDeclaratorDC(0),
|
2008-12-04 04:26:15 +08:00
|
|
|
CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()),
|
2009-06-23 04:57:11 +08:00
|
|
|
GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated),
|
2009-05-15 05:44:34 +08:00
|
|
|
CompleteTranslationUnit(CompleteTranslationUnit),
|
2009-06-14 16:02:22 +08:00
|
|
|
NumSFINAEErrors(0), CurrentInstantiationScope(0) {
|
2009-09-09 23:08:12 +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());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-23 17:13:29 +08:00
|
|
|
// Tell diagnostics how to render things from the AST library.
|
2009-02-20 07:53:20 +08:00
|
|
|
PP.getDiagnostics().SetArgToStringFn(ConvertArgToStringFn, &Context);
|
2007-02-28 09:22:02 +08:00
|
|
|
}
|
2006-11-10 14:20:45 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
|
2008-01-17 03:17:22 +08:00
|
|
|
/// 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.
|
2009-09-09 23:08:12 +08:00
|
|
|
void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
|
2009-09-15 13:13:45 +08:00
|
|
|
CastExpr::CastKind Kind, bool isLvalue) {
|
2008-09-04 16:38:01 +08:00
|
|
|
QualType ExprTy = Context.getCanonicalType(Expr->getType());
|
|
|
|
QualType TypeTy = Context.getCanonicalType(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-09-04 16:38:01 +08:00
|
|
|
if (ExprTy == TypeTy)
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-09-04 16:38:01 +08:00
|
|
|
if (Expr->getType().getTypePtr()->isPointerType() &&
|
|
|
|
Ty.getTypePtr()->isPointerType()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType ExprBaseType =
|
2008-09-04 16:38:01 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +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);
|
2009-09-09 23:08:12 +08:00
|
|
|
} else
|
2009-09-15 13:13:45 +08:00
|
|
|
Expr = new (Context) ImplicitCastExpr(Ty, Kind, 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() {
|
2009-06-23 07:06:13 +08:00
|
|
|
// C++: Perform implicit template instantiations.
|
|
|
|
//
|
|
|
|
// FIXME: When we perform these implicit instantiations, we do not carefully
|
|
|
|
// keep track of the point of instantiation (C++ [temp.point]). This means
|
|
|
|
// that name lookup that occurs within the template instantiation will
|
|
|
|
// always happen at the end of the translation unit, so it will find
|
2009-09-09 23:08:12 +08:00
|
|
|
// some names that should not be found. Although this is common behavior
|
2009-06-23 07:06:13 +08:00
|
|
|
// for C++ compilers, it is technically wrong. In the future, we either need
|
|
|
|
// to be able to filter the results of name lookup or we need to perform
|
|
|
|
// template instantiations earlier.
|
|
|
|
PerformPendingImplicitInstantiations();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-09 02:19:27 +08:00
|
|
|
// Check for #pragma weak identifiers that were never declared
|
|
|
|
// FIXME: This will cause diagnostics to be emitted in a non-determinstic
|
|
|
|
// order! Iterating over a densemap like this is bad.
|
2009-07-30 11:15:39 +08:00
|
|
|
for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator
|
2009-09-09 02:19:27 +08:00
|
|
|
I = WeakUndeclaredIdentifiers.begin(),
|
|
|
|
E = WeakUndeclaredIdentifiers.end(); I != E; ++I) {
|
|
|
|
if (I->second.getUsed()) continue;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-09 02:19:27 +08:00
|
|
|
Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared)
|
|
|
|
<< I->first;
|
2009-07-30 11:15:39 +08:00
|
|
|
}
|
|
|
|
|
2009-04-15 00:27:31 +08:00
|
|
|
if (!CompleteTranslationUnit)
|
|
|
|
return;
|
|
|
|
|
2009-03-11 07:43:53 +08:00
|
|
|
// C99 6.9.2p2:
|
|
|
|
// A declaration of an identifier for an object that has file
|
|
|
|
// scope without an initializer, and without a storage-class
|
|
|
|
// specifier or with the storage-class specifier static,
|
|
|
|
// constitutes a tentative definition. If a translation unit
|
|
|
|
// contains one or more tentative definitions for an identifier,
|
|
|
|
// and the translation unit contains no external definition for
|
|
|
|
// that identifier, then the behavior is exactly as if the
|
|
|
|
// translation unit contains a file scope declaration of that
|
|
|
|
// identifier, with the composite type as of the end of the
|
|
|
|
// translation unit, with an initializer equal to 0.
|
2009-09-09 02:19:27 +08:00
|
|
|
for (unsigned i = 0, e = TentativeDefinitionList.size(); i != e; ++i) {
|
|
|
|
VarDecl *VD = TentativeDefinitions.lookup(TentativeDefinitionList[i]);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-09 02:19:27 +08:00
|
|
|
// If the tentative definition was completed, it will be in the list, but
|
|
|
|
// not the map.
|
|
|
|
if (VD == 0 || VD->isInvalidDecl() || !VD->isTentativeDefinition(Context))
|
2009-04-22 01:11:58 +08:00
|
|
|
continue;
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
if (const IncompleteArrayType *ArrayT
|
2009-04-22 01:11:58 +08:00
|
|
|
= Context.getAsIncompleteArrayType(VD->getType())) {
|
2009-09-09 23:08:12 +08:00
|
|
|
if (RequireCompleteType(VD->getLocation(),
|
2009-04-22 01:11:58 +08:00
|
|
|
ArrayT->getElementType(),
|
2009-09-09 02:19:27 +08:00
|
|
|
diag::err_tentative_def_incomplete_type_arr)) {
|
2009-04-22 01:11:58 +08:00
|
|
|
VD->setInvalidDecl();
|
2009-09-09 02:19:27 +08:00
|
|
|
continue;
|
2009-03-11 07:43:53 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-09 02:19:27 +08:00
|
|
|
// Set the length of the array to 1 (C99 6.9.2p5).
|
|
|
|
Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
|
|
|
|
llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType T
|
2009-09-09 02:19:27 +08:00
|
|
|
= Context.getConstantArrayWithoutExprType(ArrayT->getElementType(),
|
|
|
|
One, ArrayType::Normal, 0);
|
|
|
|
VD->setType(T);
|
2009-09-09 23:08:12 +08:00
|
|
|
} else if (RequireCompleteType(VD->getLocation(), VD->getType(),
|
2009-04-22 01:11:58 +08:00
|
|
|
diag::err_tentative_def_incomplete_type))
|
|
|
|
VD->setInvalidDecl();
|
|
|
|
|
|
|
|
// Notify the consumer that we've completed a tentative definition.
|
|
|
|
if (!VD->isInvalidDecl())
|
|
|
|
Consumer.CompleteTentativeDefinition(VD);
|
|
|
|
|
2009-03-11 07:43:53 +08:00
|
|
|
}
|
2008-08-23 11:19:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-10 13:17:58 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Helper functions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-08-09 01:45:02 +08:00
|
|
|
DeclContext *Sema::getFunctionLevelDeclContext() {
|
2009-08-09 01:48:49 +08:00
|
|
|
DeclContext *DC = PreDeclaratorDC ? PreDeclaratorDC : CurContext;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-09 01:45:02 +08:00
|
|
|
while (isa<BlockDecl>(DC))
|
|
|
|
DC = DC->getParent();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-09 01:45:02 +08:00
|
|
|
return DC;
|
|
|
|
}
|
|
|
|
|
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() {
|
2009-08-09 01:45:02 +08:00
|
|
|
DeclContext *DC = getFunctionLevelDeclContext();
|
2008-12-05 07:50:19 +08:00
|
|
|
return dyn_cast<FunctionDecl>(DC);
|
|
|
|
}
|
|
|
|
|
2008-08-11 13:35:13 +08:00
|
|
|
ObjCMethodDecl *Sema::getCurMethodDecl() {
|
2009-08-09 01:45:02 +08:00
|
|
|
DeclContext *DC = getFunctionLevelDeclContext();
|
2008-11-18 00:28:52 +08:00
|
|
|
return dyn_cast<ObjCMethodDecl>(DC);
|
2008-08-11 13:35:13 +08:00
|
|
|
}
|
2008-12-05 07:50:19 +08:00
|
|
|
|
|
|
|
NamedDecl *Sema::getCurFunctionOrMethodDecl() {
|
2009-08-09 01:45:02 +08:00
|
|
|
DeclContext *DC = getFunctionLevelDeclContext();
|
2008-12-05 07:50:19 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void Sema::DiagnoseMissingMember(SourceLocation MemberLoc,
|
2009-08-30 08:54:35 +08:00
|
|
|
DeclarationName Member,
|
|
|
|
NestedNameSpecifier *NNS, SourceRange Range) {
|
|
|
|
switch (NNS->getKind()) {
|
|
|
|
default: assert(0 && "Unexpected nested name specifier kind!");
|
|
|
|
case NestedNameSpecifier::TypeSpec: {
|
|
|
|
const Type *Ty = Context.getCanonicalType(NNS->getAsType());
|
|
|
|
RecordDecl *RD = cast<RecordType>(Ty)->getDecl();
|
|
|
|
Diag(MemberLoc, diag::err_typecheck_record_no_member)
|
2009-08-30 14:49:43 +08:00
|
|
|
<< Member << RD->getTagKind() << RD << Range;
|
2009-08-30 08:54:35 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case NestedNameSpecifier::Namespace: {
|
|
|
|
Diag(MemberLoc, diag::err_typecheck_namespace_no_member)
|
2009-08-30 14:49:43 +08:00
|
|
|
<< Member << NNS->getAsNamespace() << Range;
|
2009-08-30 08:54:35 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case NestedNameSpecifier::Global: {
|
2009-08-30 14:49:43 +08:00
|
|
|
Diag(MemberLoc, diag::err_typecheck_global_namespace_no_member)
|
2009-08-30 08:54:35 +08:00
|
|
|
<< Member << Range;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-21 06:48:49 +08:00
|
|
|
Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
|
2009-06-14 15:33:30 +08:00
|
|
|
if (!this->Emit())
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-21 06:48:49 +08:00
|
|
|
// If this is not a note, and we're in a template instantiation
|
|
|
|
// that is different from the last template instantiation where
|
|
|
|
// we emitted an error, print a template instantiation
|
|
|
|
// backtrace.
|
|
|
|
if (!SemaRef.Diags.isBuiltinNote(DiagID) &&
|
|
|
|
!SemaRef.ActiveTemplateInstantiations.empty() &&
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.ActiveTemplateInstantiations.back()
|
2009-03-21 06:48:49 +08:00
|
|
|
!= SemaRef.LastTemplateInstantiationErrorContext) {
|
|
|
|
SemaRef.PrintInstantiationStack();
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.LastTemplateInstantiationErrorContext
|
2009-03-21 06:48:49 +08:00
|
|
|
= SemaRef.ActiveTemplateInstantiations.back();
|
|
|
|
}
|
|
|
|
}
|
Add support for retrieving the Doxygen comment associated with a given
declaration in the AST.
The new ASTContext::getCommentForDecl function searches for a comment
that is attached to the given declaration, and returns that comment,
which may be composed of several comment blocks.
Comments are always available in an AST. However, to avoid harming
performance, we don't actually parse the comments. Rather, we keep the
source ranges of all of the comments within a large, sorted vector,
then lazily extract comments via a binary search in that vector only
when needed (which never occurs in a "normal" compile).
Comments are written to a precompiled header/AST file as a blob of
source ranges. That blob is only lazily loaded when one requests a
comment for a declaration (this never occurs in a "normal" compile).
The indexer testbed now supports comment extraction. When the
-point-at location points to a declaration with a Doxygen-style
comment, the indexer testbed prints the associated comment
block(s). See test/Index/comments.c for an example.
Some notes:
- We don't actually attempt to parse the comment blocks themselves,
beyond identifying them as Doxygen comment blocks to associate them
with a declaration.
- We won't find comment blocks that aren't adjacent to the
declaration, because we start our search based on the location of
the declaration.
- We don't go through the necessary hops to find, for example,
whether some redeclaration of a declaration has comments when our
current declaration does not. Similarly, we don't attempt to
associate a \param Foo marker in a function body comment with the
parameter named Foo (although that is certainly possible).
- Verification of my "no performance impact" claims is still "to be
done".
llvm-svn: 74704
2009-07-03 01:08:52 +08:00
|
|
|
|
2009-08-27 06:33:56 +08:00
|
|
|
Sema::SemaDiagnosticBuilder
|
|
|
|
Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) {
|
|
|
|
SemaDiagnosticBuilder Builder(Diag(Loc, PD.getDiagID()));
|
|
|
|
PD.Emit(Builder);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-27 06:33:56 +08:00
|
|
|
return Builder;
|
|
|
|
}
|
|
|
|
|
Add support for retrieving the Doxygen comment associated with a given
declaration in the AST.
The new ASTContext::getCommentForDecl function searches for a comment
that is attached to the given declaration, and returns that comment,
which may be composed of several comment blocks.
Comments are always available in an AST. However, to avoid harming
performance, we don't actually parse the comments. Rather, we keep the
source ranges of all of the comments within a large, sorted vector,
then lazily extract comments via a binary search in that vector only
when needed (which never occurs in a "normal" compile).
Comments are written to a precompiled header/AST file as a blob of
source ranges. That blob is only lazily loaded when one requests a
comment for a declaration (this never occurs in a "normal" compile).
The indexer testbed now supports comment extraction. When the
-point-at location points to a declaration with a Doxygen-style
comment, the indexer testbed prints the associated comment
block(s). See test/Index/comments.c for an example.
Some notes:
- We don't actually attempt to parse the comment blocks themselves,
beyond identifying them as Doxygen comment blocks to associate them
with a declaration.
- We won't find comment blocks that aren't adjacent to the
declaration, because we start our search based on the location of
the declaration.
- We don't go through the necessary hops to find, for example,
whether some redeclaration of a declaration has comments when our
current declaration does not. Similarly, we don't attempt to
associate a \param Foo marker in a function body comment with the
parameter named Foo (although that is certainly possible).
- Verification of my "no performance impact" claims is still "to be
done".
llvm-svn: 74704
2009-07-03 01:08:52 +08:00
|
|
|
void Sema::ActOnComment(SourceRange Comment) {
|
|
|
|
Context.Comments.push_back(Comment);
|
|
|
|
}
|
2009-08-27 06:33:56 +08:00
|
|
|
|