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"
|
2010-01-10 20:58:08 +08:00
|
|
|
#include "TargetAttributesSema.h"
|
2009-07-30 11:15:39 +08:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2010-02-01 06:27:38 +08:00
|
|
|
#include "llvm/ADT/SmallSet.h"
|
2009-11-07 11:30:10 +08:00
|
|
|
#include "llvm/ADT/APFloat.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"
|
2010-02-10 06:26:47 +08:00
|
|
|
#include "clang/AST/ASTDiagnostic.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-10-14 05:16:44 +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) {
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *TInfo;
|
2009-10-24 16:00:42 +08:00
|
|
|
|
2009-04-30 14:18:40 +08:00
|
|
|
// Install [u]int128_t for 64-bit targets.
|
2009-12-07 10:54:59 +08:00
|
|
|
TInfo = Context.getTrivialTypeSourceInfo(Context.Int128Ty);
|
2009-04-30 14:18:40 +08:00
|
|
|
PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
|
|
|
|
SourceLocation(),
|
|
|
|
&Context.Idents.get("__int128_t"),
|
2009-12-07 10:54:59 +08:00
|
|
|
TInfo), TUScope);
|
2009-10-24 16:00:42 +08:00
|
|
|
|
2009-12-07 10:54:59 +08:00
|
|
|
TInfo = Context.getTrivialTypeSourceInfo(Context.UnsignedInt128Ty);
|
2009-04-30 14:18:40 +08:00
|
|
|
PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
|
|
|
|
SourceLocation(),
|
|
|
|
&Context.Idents.get("__uint128_t"),
|
2009-12-07 10:54:59 +08:00
|
|
|
TInfo), TUScope);
|
2009-04-30 14:18:40 +08:00
|
|
|
}
|
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()) {
|
2009-11-22 03:53:08 +08:00
|
|
|
// Create the built-in typedef for 'SEL'.
|
2009-11-24 02:04:25 +08:00
|
|
|
QualType SelT = Context.getPointerType(Context.ObjCBuiltinSelTy);
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *SelInfo = Context.getTrivialTypeSourceInfo(SelT);
|
2009-10-24 16:00:42 +08:00
|
|
|
TypedefDecl *SelTypedef
|
|
|
|
= TypedefDecl::Create(Context, CurContext, SourceLocation(),
|
|
|
|
&Context.Idents.get("SEL"), SelInfo);
|
2009-04-24 06:29:11 +08:00
|
|
|
PushOnScopeChains(SelTypedef, TUScope);
|
|
|
|
Context.setObjCSelType(Context.getTypeDeclType(SelTypedef));
|
2009-11-26 07:07:42 +08:00
|
|
|
Context.ObjCSelRedefinitionType = Context.getObjCSelType();
|
2009-04-24 06:29:11 +08:00
|
|
|
}
|
|
|
|
|
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));
|
2009-11-19 07:15:37 +08:00
|
|
|
PushOnScopeChains(ProtocolDecl, TUScope, false);
|
2009-04-24 06:29:11 +08:00
|
|
|
}
|
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-10-24 16:00:42 +08:00
|
|
|
QualType IdT = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy);
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *IdInfo = Context.getTrivialTypeSourceInfo(IdT);
|
2009-10-24 16:00:42 +08:00
|
|
|
TypedefDecl *IdTypedef
|
|
|
|
= TypedefDecl::Create(Context, CurContext, SourceLocation(),
|
|
|
|
&Context.Idents.get("id"), IdInfo);
|
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-10-24 16:00:42 +08:00
|
|
|
QualType ClassType
|
|
|
|
= Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy);
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *ClassInfo = Context.getTrivialTypeSourceInfo(ClassType);
|
2009-10-24 16:00:42 +08:00
|
|
|
TypedefDecl *ClassTypedef
|
|
|
|
= TypedefDecl::Create(Context, CurContext, SourceLocation(),
|
|
|
|
&Context.Idents.get("Class"), ClassInfo);
|
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,
|
2009-11-13 16:58:20 +08:00
|
|
|
bool CompleteTranslationUnit,
|
|
|
|
CodeCompleteConsumer *CodeCompleter)
|
2010-01-10 20:58:08 +08:00
|
|
|
: TheTargetAttributesSema(0),
|
|
|
|
LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
|
2009-09-09 23:08:12 +08:00
|
|
|
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
|
2009-11-13 16:58:20 +08:00
|
|
|
ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0),
|
2009-12-19 18:53:49 +08:00
|
|
|
CurBlock(0), PackContext(0), ParsingDeclDepth(0),
|
Initial implementation of a code-completion interface in Clang. In
essence, code completion is triggered by a magic "code completion"
token produced by the lexer [*], which the parser recognizes at
certain points in the grammar. The parser then calls into the Action
object with the appropriate CodeCompletionXXX action.
Sema implements the CodeCompletionXXX callbacks by performing minimal
translation, then forwarding them to a CodeCompletionConsumer
subclass, which uses the results of semantic analysis to provide
code-completion results. At present, only a single, "printing" code
completion consumer is available, for regression testing and
debugging. However, the design is meant to permit other
code-completion consumers.
This initial commit contains two code-completion actions: one for
member access, e.g., "x." or "p->", and one for
nested-name-specifiers, e.g., "std::". More code-completion actions
will follow, along with improved gathering of code-completion results
for the various contexts.
[*] In the current -code-completion-dump testing/debugging mode, the
file is truncated at the completion point and EOF is translated into
"code completion".
llvm-svn: 82166
2009-09-18 05:32:03 +08:00
|
|
|
IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
|
2009-11-26 08:44:06 +08:00
|
|
|
GlobalNewDeleteDeclared(false),
|
2009-05-15 05:44:34 +08:00
|
|
|
CompleteTranslationUnit(CompleteTranslationUnit),
|
2009-11-12 05:54:23 +08:00
|
|
|
NumSFINAEErrors(0), NonInstantiationEntries(0),
|
2010-02-02 10:07:01 +08:00
|
|
|
CurrentInstantiationScope(0), TyposCorrected(0)
|
2009-11-12 05:54:23 +08:00
|
|
|
{
|
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
|
|
|
|
2010-03-02 04:59:53 +08:00
|
|
|
NumErrorsAtStartOfFunction = 0;
|
|
|
|
|
2008-11-23 17:13:29 +08:00
|
|
|
// Tell diagnostics how to render things from the AST library.
|
2010-02-10 06:26:47 +08:00
|
|
|
PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
|
|
|
|
&Context);
|
2009-11-26 08:44:06 +08:00
|
|
|
|
|
|
|
ExprEvalContexts.push_back(
|
|
|
|
ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0));
|
2007-02-28 09:22:02 +08:00
|
|
|
}
|
2006-11-10 14:20:45 +08:00
|
|
|
|
2010-01-10 20:58:08 +08:00
|
|
|
Sema::~Sema() {
|
|
|
|
if (PackContext) FreePackedContext();
|
|
|
|
delete TheTargetAttributesSema;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2009-11-07 11:30:10 +08:00
|
|
|
if (Expr->getType()->isPointerType() && Ty->isPointerType()) {
|
|
|
|
QualType ExprBaseType = cast<PointerType>(ExprTy)->getPointeeType();
|
|
|
|
QualType BaseType = cast<PointerType>(TypeTy)->getPointeeType();
|
2008-09-04 16:38:01 +08:00
|
|
|
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
|
|
|
|
2010-01-05 07:31:57 +08:00
|
|
|
CheckImplicitConversion(Expr, Ty);
|
2009-11-07 11:30:10 +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)) {
|
2009-09-15 13:28:24 +08:00
|
|
|
if (ImpCast->getCastKind() == Kind) {
|
|
|
|
ImpCast->setType(Ty);
|
|
|
|
ImpCast->setLvalueCast(isLvalue);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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-12-07 16:24:59 +08:00
|
|
|
|
2010-02-12 08:07:30 +08:00
|
|
|
// Remove functions that turned out to be used.
|
|
|
|
UnusedStaticFuncs.erase(std::remove_if(UnusedStaticFuncs.begin(),
|
|
|
|
UnusedStaticFuncs.end(),
|
|
|
|
std::mem_fun(&FunctionDecl::isUsed)),
|
|
|
|
UnusedStaticFuncs.end());
|
|
|
|
|
2009-12-07 16:24:59 +08:00
|
|
|
while (1) {
|
|
|
|
// 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
|
|
|
|
// some names that should not be found. Although this is common behavior
|
|
|
|
// 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();
|
|
|
|
|
|
|
|
/// If ProcessPendingClassesWithUnmarkedVirtualMembers ends up marking
|
|
|
|
/// any virtual member functions it might lead to more pending template
|
|
|
|
/// instantiations, which is why we need to loop here.
|
|
|
|
if (!ProcessPendingClassesWithUnmarkedVirtualMembers())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
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.
|
2010-02-01 06:27:38 +08:00
|
|
|
llvm::SmallSet<VarDecl *, 32> Seen;
|
|
|
|
for (unsigned i = 0, e = TentativeDefinitions.size(); i != e; ++i) {
|
|
|
|
VarDecl *VD = TentativeDefinitions[i]->getActingDefinition();
|
|
|
|
|
|
|
|
// If the tentative definition was completed, getActingDefinition() returns
|
|
|
|
// null. If we've already seen this variable before, insert()'s second
|
|
|
|
// return value is false.
|
|
|
|
if (VD == 0 || VD->isInvalidDecl() || !Seen.insert(VD))
|
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-10-16 08:14:28 +08:00
|
|
|
QualType T = Context.getConstantArrayType(ArrayT->getElementType(),
|
|
|
|
One, ArrayType::Normal, 0);
|
2009-09-09 02:19:27 +08:00
|
|
|
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
|
|
|
}
|
2010-02-12 08:07:30 +08:00
|
|
|
|
|
|
|
// Output warning for unused functions.
|
|
|
|
for (std::vector<FunctionDecl*>::iterator
|
|
|
|
F = UnusedStaticFuncs.begin(),
|
|
|
|
FEnd = UnusedStaticFuncs.end();
|
|
|
|
F != FEnd;
|
|
|
|
++F)
|
|
|
|
Diag((*F)->getLocation(), diag::warn_unused_function) << (*F)->getDeclName();
|
|
|
|
|
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-12-19 18:53:49 +08:00
|
|
|
DeclContext *DC = 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-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
|
|
|
|