aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/Sema.cpp
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-10-14 18:03:49 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-10-14 18:03:49 +0000
commit4c8b24812ddcd1dedaca343a6d4e76f91f398981 (patch)
tree137ebebcae16fb0ce7ab4af456992bbd8d22fced /lib/Sema/Sema.cpp
parent5362a71c02e7d448a8ce98cf00c47e353fba5d04 (diff)
downloadsrc-4c8b24812ddcd1dedaca343a6d4e76f91f398981.tar.gz
src-4c8b24812ddcd1dedaca343a6d4e76f91f398981.zip
Update clang to r84119.vendor/clang/clang-r84119
Notes
Notes: svn path=/vendor/clang/dist/; revision=198092 svn path=/vendor/clang/clang-84119/; revision=198093; tag=vendor/clang/clang-r84119
Diffstat (limited to 'lib/Sema/Sema.cpp')
-rw-r--r--lib/Sema/Sema.cpp329
1 files changed, 210 insertions, 119 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index d1e8e2104d50..ba05a07f2654 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -13,15 +13,65 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "llvm/ADT/DenseMap.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
using namespace clang;
-/// ConvertQualTypeToStringFn - This function is used to pretty print the
+/// \brief Convert the given type to a string suitable for printing as part of
+/// a diagnostic.
+///
+/// \param Context the context in which the type was allocated
+/// \param Ty the type to print
+static std::string ConvertTypeToDiagnosticString(ASTContext &Context,
+ QualType Ty) {
+ // FIXME: Playing with std::string is really slow.
+ std::string S = Ty.getAsString(Context.PrintingPolicy);
+
+ // 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.
+ QualType DesugaredTy = Ty.getDesugaredType();
+
+ 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) &&
+
+ // Don't aka just because we saw an elaborated type...
+ (!isa<ElaboratedType>(Ty) ||
+ cast<ElaboratedType>(Ty)->desugar() != DesugaredTy) &&
+
+ // ...or a qualified name type...
+ (!isa<QualifiedNameType>(Ty) ||
+ cast<QualifiedNameType>(Ty)->desugar() != DesugaredTy) &&
+
+ // ...or a non-dependent template specialization.
+ (!isa<TemplateSpecializationType>(Ty) || Ty->isDependentType()) &&
+
+ // Don't desugar magic Objective-C types.
+ Ty.getUnqualifiedType() != Context.getObjCIdType() &&
+ Ty.getUnqualifiedType() != Context.getObjCClassType() &&
+ Ty.getUnqualifiedType() != Context.getObjCSelType() &&
+ Ty.getUnqualifiedType() != Context.getObjCProtoType() &&
+
+ // Not va_list.
+ Ty.getUnqualifiedType() != Context.getBuiltinVaListType()) {
+ S = "'"+S+"' (aka '";
+ S += DesugaredTy.getAsString(Context.PrintingPolicy);
+ S += "')";
+ return S;
+ }
+
+ S = "'" + S + "'";
+ return S;
+}
+
+/// ConvertQualTypeToStringFn - This function is used to pretty print the
/// specified QualType as a string in diagnostics.
static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
const char *Modifier, unsigned ModLen,
@@ -29,48 +79,21 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
llvm::SmallVectorImpl<char> &Output,
void *Cookie) {
ASTContext &Context = *static_cast<ASTContext*>(Cookie);
-
+
std::string S;
+ bool NeedQuotes = true;
if (Kind == Diagnostic::ak_qualtype) {
assert(ModLen == 0 && ArgLen == 0 &&
"Invalid modifier for QualType argument");
QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));
-
- // FIXME: Playing with std::string is really slow.
- S = Ty.getAsString(Context.PrintingPolicy);
-
- // 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.
- QualType DesugaredTy = Ty->getDesugaredType(true);
- DesugaredTy.setCVRQualifiers(DesugaredTy.getCVRQualifiers() |
- Ty.getCVRQualifiers());
-
- 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) &&
-
- // Don't desugar magic Objective-C types.
- Ty.getUnqualifiedType() != Context.getObjCIdType() &&
- Ty.getUnqualifiedType() != Context.getObjCSelType() &&
- Ty.getUnqualifiedType() != Context.getObjCProtoType() &&
- Ty.getUnqualifiedType() != Context.getObjCClassType() &&
-
- // Not va_list.
- Ty.getUnqualifiedType() != Context.getBuiltinVaListType()) {
- S = "'"+S+"' (aka '";
- S += DesugaredTy.getAsString(Context.PrintingPolicy);
- S += "')";
- Output.append(S.begin(), S.end());
- return;
- }
-
+ S = ConvertTypeToDiagnosticString(Context, Ty);
+ NeedQuotes = false;
} else if (Kind == Diagnostic::ak_declarationname) {
-
+
DeclarationName N = DeclarationName::getFromOpaqueInteger(Val);
S = N.getAsString();
-
+
if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0)
S = '+' + S;
else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12) && ArgLen==0)
@@ -78,30 +101,73 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
else
assert(ModLen == 0 && ArgLen == 0 &&
"Invalid modifier for DeclarationName argument");
- } else {
- assert(Kind == Diagnostic::ak_nameddecl);
+ } else if (Kind == Diagnostic::ak_nameddecl) {
+ bool Qualified;
if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0)
- S = reinterpret_cast<NamedDecl*>(Val)->getQualifiedNameAsString();
- else {
+ Qualified = true;
+ else {
assert(ModLen == 0 && ArgLen == 0 &&
"Invalid modifier for NamedDecl* argument");
- S = reinterpret_cast<NamedDecl*>(Val)->getNameAsString();
+ Qualified = false;
+ }
+ reinterpret_cast<NamedDecl*>(Val)->getNameForDiagnostic(S,
+ Context.PrintingPolicy,
+ Qualified);
+ } else if (Kind == Diagnostic::ak_nestednamespec) {
+ llvm::raw_string_ostream OS(S);
+ reinterpret_cast<NestedNameSpecifier*> (Val)->print(OS,
+ Context.PrintingPolicy);
+ NeedQuotes = false;
+ } else {
+ assert(Kind == Diagnostic::ak_declcontext);
+ DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
+ NeedQuotes = false;
+ if (!DC) {
+ assert(false && "Should never have a null declaration context");
+ S = "unknown context";
+ } else if (DC->isTranslationUnit()) {
+ // FIXME: Get these strings from some localized place
+ if (Context.getLangOptions().CPlusPlus)
+ S = "the global namespace";
+ else
+ S = "the global scope";
+ } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) {
+ S = ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type));
+ NeedQuotes = false;
+ } else {
+ // FIXME: Get these strings from some localized place
+ NamedDecl *ND = cast<NamedDecl>(DC);
+ if (isa<NamespaceDecl>(ND))
+ S += "namespace ";
+ else if (isa<ObjCMethodDecl>(ND))
+ S += "method ";
+ else if (isa<FunctionDecl>(ND))
+ S += "function ";
+
+ S += "'";
+ ND->getNameForDiagnostic(S, Context.PrintingPolicy, true);
+ S += "'";
+ NeedQuotes = false;
}
}
+
+ if (NeedQuotes)
+ Output.push_back('\'');
- Output.push_back('\'');
Output.append(S.begin(), S.end());
- Output.push_back('\'');
+
+ if (NeedQuotes)
+ Output.push_back('\'');
}
static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name) {
if (C.getLangOptions().CPlusPlus)
- return CXXRecordDecl::Create(C, TagDecl::TK_struct,
+ return CXXRecordDecl::Create(C, TagDecl::TK_struct,
C.getTranslationUnitDecl(),
SourceLocation(), &C.Idents.get(Name));
- return RecordDecl::Create(C, TagDecl::TK_struct,
+ return RecordDecl::Create(C, TagDecl::TK_struct,
C.getTranslationUnitDecl(),
SourceLocation(), &C.Idents.get(Name));
}
@@ -109,7 +175,7 @@ static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name) {
void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
TUScope = S;
PushDeclContext(S, Context.getTranslationUnitDecl());
-
+
if (PP.getTargetInfo().getPointerWidth(0) >= 64) {
// Install [u]int128_t for 64-bit targets.
PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
@@ -121,16 +187,16 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
&Context.Idents.get("__uint128_t"),
Context.UnsignedInt128Ty), TUScope);
}
-
-
+
+
if (!PP.getLangOptions().ObjC1) return;
-
+
// Built-in ObjC types may already be set by PCHReader (hence isNull checks).
if (Context.getObjCSelType().isNull()) {
// Synthesize "typedef struct objc_selector *SEL;"
RecordDecl *SelTag = CreateStructDecl(Context, "objc_selector");
PushOnScopeChains(SelTag, TUScope);
-
+
QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag));
TypedefDecl *SelTypedef = TypedefDecl::Create(Context, CurContext,
SourceLocation(),
@@ -140,74 +206,72 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
Context.setObjCSelType(Context.getTypeDeclType(SelTypedef));
}
- if (Context.getObjCClassType().isNull()) {
- RecordDecl *ClassTag = CreateStructDecl(Context, "objc_class");
- QualType ClassT = Context.getPointerType(Context.getTagDeclType(ClassTag));
- TypedefDecl *ClassTypedef =
- TypedefDecl::Create(Context, CurContext, SourceLocation(),
- &Context.Idents.get("Class"), ClassT);
- PushOnScopeChains(ClassTag, TUScope);
- PushOnScopeChains(ClassTypedef, TUScope);
- Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
- }
-
// Synthesize "@class Protocol;
if (Context.getObjCProtoType().isNull()) {
ObjCInterfaceDecl *ProtocolDecl =
ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
- &Context.Idents.get("Protocol"),
+ &Context.Idents.get("Protocol"),
SourceLocation(), true);
Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
PushOnScopeChains(ProtocolDecl, TUScope);
}
-
- // Synthesize "typedef struct objc_object { Class isa; } *id;"
+ // Create the built-in typedef for 'id'.
if (Context.getObjCIdType().isNull()) {
- RecordDecl *ObjectTag = CreateStructDecl(Context, "objc_object");
-
- QualType ObjT = Context.getPointerType(Context.getTagDeclType(ObjectTag));
- PushOnScopeChains(ObjectTag, TUScope);
- TypedefDecl *IdTypedef = TypedefDecl::Create(Context, CurContext,
- SourceLocation(),
- &Context.Idents.get("id"),
- ObjT);
+ TypedefDecl *IdTypedef =
+ TypedefDecl::Create(
+ Context, CurContext, SourceLocation(), &Context.Idents.get("id"),
+ Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy)
+ );
PushOnScopeChains(IdTypedef, TUScope);
Context.setObjCIdType(Context.getTypeDeclType(IdTypedef));
+ Context.ObjCIdRedefinitionType = Context.getObjCIdType();
+ }
+ // Create the built-in typedef for 'Class'.
+ if (Context.getObjCClassType().isNull()) {
+ TypedefDecl *ClassTypedef =
+ TypedefDecl::Create(
+ Context, CurContext, SourceLocation(), &Context.Idents.get("Class"),
+ Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy)
+ );
+ PushOnScopeChains(ClassTypedef, TUScope);
+ Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
+ Context.ObjCClassRedefinitionType = Context.getObjCClassType();
}
}
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
bool CompleteTranslationUnit)
: LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
- Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
- ExternalSource(0), CurContext(0), PreDeclaratorDC(0),
- CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()),
+ Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
+ ExternalSource(0), CodeCompleter(0), CurContext(0),
+ PreDeclaratorDC(0), CurBlock(0), PackContext(0),
+ IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated),
CompleteTranslationUnit(CompleteTranslationUnit),
NumSFINAEErrors(0), CurrentInstantiationScope(0) {
-
- StdNamespace = 0;
+
TUScope = 0;
if (getLangOptions().CPlusPlus)
FieldCollector.reset(new CXXFieldCollector());
-
+
// Tell diagnostics how to render things from the AST library.
PP.getDiagnostics().SetArgToStringFn(ConvertArgToStringFn, &Context);
}
-/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
+/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
/// If there is already an implicit cast, merge into the existing one.
/// If isLvalue, the result of the cast is an lvalue.
-void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, bool isLvalue) {
+void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
+ CastExpr::CastKind Kind, bool isLvalue) {
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 =
+ QualType ExprBaseType =
cast<PointerType>(ExprTy.getUnqualifiedType())->getPointeeType();
QualType BaseType =
cast<PointerType>(TypeTy.getUnqualifiedType())->getPointeeType();
@@ -216,12 +280,16 @@ void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, bool isLvalue) {
<< Expr->getSourceRange();
}
}
-
+
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
- ImpCast->setType(Ty);
- ImpCast->setLvalueCast(isLvalue);
- } else
- Expr = new (Context) ImplicitCastExpr(Ty, Expr, isLvalue);
+ if (ImpCast->getCastKind() == Kind) {
+ ImpCast->setType(Ty);
+ ImpCast->setLvalueCast(isLvalue);
+ return;
+ }
+ }
+
+ Expr = new (Context) ImplicitCastExpr(Ty, Kind, Expr, isLvalue);
}
void Sema::DeleteExpr(ExprTy *E) {
@@ -241,12 +309,24 @@ void Sema::ActOnEndOfTranslationUnit() {
// 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
+ // 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();
-
+
+ // 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.
+ for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator
+ I = WeakUndeclaredIdentifiers.begin(),
+ E = WeakUndeclaredIdentifiers.end(); I != E; ++I) {
+ if (I->second.getUsed()) continue;
+
+ Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared)
+ << I->first;
+ }
+
if (!CompleteTranslationUnit)
return;
@@ -261,32 +341,31 @@ void Sema::ActOnEndOfTranslationUnit() {
// 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.
- for (llvm::DenseMap<DeclarationName, VarDecl *>::iterator
- D = TentativeDefinitions.begin(),
- DEnd = TentativeDefinitions.end();
- D != DEnd; ++D) {
- VarDecl *VD = D->second;
+ for (unsigned i = 0, e = TentativeDefinitionList.size(); i != e; ++i) {
+ VarDecl *VD = TentativeDefinitions.lookup(TentativeDefinitionList[i]);
- if (VD->isInvalidDecl() || !VD->isTentativeDefinition(Context))
+ // If the tentative definition was completed, it will be in the list, but
+ // not the map.
+ if (VD == 0 || VD->isInvalidDecl() || !VD->isTentativeDefinition(Context))
continue;
- if (const IncompleteArrayType *ArrayT
+ if (const IncompleteArrayType *ArrayT
= Context.getAsIncompleteArrayType(VD->getType())) {
- if (RequireCompleteType(VD->getLocation(),
+ if (RequireCompleteType(VD->getLocation(),
ArrayT->getElementType(),
- diag::err_tentative_def_incomplete_type_arr))
+ diag::err_tentative_def_incomplete_type_arr)) {
VD->setInvalidDecl();
- else {
- // 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);
- QualType T
- = Context.getConstantArrayType(ArrayT->getElementType(),
- One, ArrayType::Normal, 0);
- VD->setType(T);
+ continue;
}
- } else if (RequireCompleteType(VD->getLocation(), VD->getType(),
+
+ // 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);
+ QualType T
+ = Context.getConstantArrayWithoutExprType(ArrayT->getElementType(),
+ One, ArrayType::Normal, 0);
+ VD->setType(T);
+ } else if (RequireCompleteType(VD->getLocation(), VD->getType(),
diag::err_tentative_def_incomplete_type))
VD->setInvalidDecl();
@@ -302,27 +381,30 @@ void Sema::ActOnEndOfTranslationUnit() {
// Helper functions.
//===----------------------------------------------------------------------===//
+DeclContext *Sema::getFunctionLevelDeclContext() {
+ DeclContext *DC = PreDeclaratorDC ? PreDeclaratorDC : CurContext;
+
+ while (isa<BlockDecl>(DC))
+ DC = DC->getParent();
+
+ return DC;
+}
+
/// 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();
+ DeclContext *DC = getFunctionLevelDeclContext();
return dyn_cast<FunctionDecl>(DC);
}
ObjCMethodDecl *Sema::getCurMethodDecl() {
- DeclContext *DC = CurContext;
- while (isa<BlockDecl>(DC))
- DC = DC->getParent();
+ DeclContext *DC = getFunctionLevelDeclContext();
return dyn_cast<ObjCMethodDecl>(DC);
}
NamedDecl *Sema::getCurFunctionOrMethodDecl() {
- DeclContext *DC = CurContext;
- while (isa<BlockDecl>(DC))
- DC = DC->getParent();
+ DeclContext *DC = getFunctionLevelDeclContext();
if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC))
return cast<NamedDecl>(DC);
return 0;
@@ -331,21 +413,30 @@ NamedDecl *Sema::getCurFunctionOrMethodDecl() {
Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
if (!this->Emit())
return;
-
+
// 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() &&
- SemaRef.ActiveTemplateInstantiations.back()
+ SemaRef.ActiveTemplateInstantiations.back()
!= SemaRef.LastTemplateInstantiationErrorContext) {
SemaRef.PrintInstantiationStack();
- SemaRef.LastTemplateInstantiationErrorContext
+ SemaRef.LastTemplateInstantiationErrorContext
= SemaRef.ActiveTemplateInstantiations.back();
}
}
+Sema::SemaDiagnosticBuilder
+Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) {
+ SemaDiagnosticBuilder Builder(Diag(Loc, PD.getDiagID()));
+ PD.Emit(Builder);
+
+ return Builder;
+}
+
void Sema::ActOnComment(SourceRange Comment) {
Context.Comments.push_back(Comment);
}
+