From fd035e6496665b1f1197868e21cb0a4594e8db6e Mon Sep 17 00:00:00 2001 From: rdivacky Date: Tue, 16 Feb 2010 09:31:36 +0000 Subject: Update clang to r96341. --- lib/Sema/Sema.cpp | 280 ++++++------------------------------------------------ 1 file changed, 28 insertions(+), 252 deletions(-) (limited to 'lib/Sema/Sema.cpp') diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 171101b..38c842e 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -15,260 +15,18 @@ #include "Sema.h" #include "TargetAttributesSema.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/APFloat.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.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; - -/// Determines whether we should have an a.k.a. clause when -/// pretty-printing a type. There are three main criteria: -/// -/// 1) Some types provide very minimal sugar that doesn't impede the -/// user's understanding --- for example, elaborated type -/// specifiers. If this is all the sugar we see, we don't want an -/// a.k.a. clause. -/// 2) Some types are technically sugared but are much more familiar -/// when seen in their sugared form --- for example, va_list, -/// vector types, and the magic Objective C types. We don't -/// want to desugar these, even if we do produce an a.k.a. clause. -/// 3) Some types may have already been desugared previously in this diagnostic. -/// if this is the case, doing another "aka" would just be clutter. -/// -static bool ShouldAKA(ASTContext &Context, QualType QT, - const Diagnostic::ArgumentValue *PrevArgs, - unsigned NumPrevArgs, - QualType &DesugaredQT) { - QualType InputTy = QT; - - bool AKA = false; - QualifierCollector Qc; - - while (true) { - const Type *Ty = Qc.strip(QT); - - // Don't aka just because we saw an elaborated type... - if (isa(Ty)) { - QT = cast(Ty)->desugar(); - continue; - } - - // ...or a qualified name type... - if (isa(Ty)) { - QT = cast(Ty)->desugar(); - continue; - } - - // ...or a substituted template type parameter. - if (isa(Ty)) { - QT = cast(Ty)->desugar(); - continue; - } - - // Don't desugar template specializations. - if (isa(Ty)) - break; - - // Don't desugar magic Objective-C types. - if (QualType(Ty,0) == Context.getObjCIdType() || - QualType(Ty,0) == Context.getObjCClassType() || - QualType(Ty,0) == Context.getObjCSelType() || - QualType(Ty,0) == Context.getObjCProtoType()) - break; - - // Don't desugar va_list. - if (QualType(Ty,0) == Context.getBuiltinVaListType()) - break; - - // Otherwise, do a single-step desugar. - QualType Underlying; - bool IsSugar = false; - switch (Ty->getTypeClass()) { -#define ABSTRACT_TYPE(Class, Base) -#define TYPE(Class, Base) \ - case Type::Class: { \ - const Class##Type *CTy = cast(Ty); \ - if (CTy->isSugared()) { \ - IsSugar = true; \ - Underlying = CTy->desugar(); \ - } \ - break; \ - } -#include "clang/AST/TypeNodes.def" - } - - // If it wasn't sugared, we're done. - if (!IsSugar) - break; - - // 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". - if (isa(Underlying)) - break; - - // Don't desugar through the primary typedef of an anonymous type. - if (isa(Underlying) && isa(QT)) - if (cast(Underlying)->getDecl()->getTypedefForAnonDecl() == - cast(QT)->getDecl()) - break; - - // Otherwise, we're tearing through something opaque; note that - // we'll eventually need an a.k.a. clause and keep going. - AKA = true; - QT = Underlying; - continue; - } - - // If we never tore through opaque sugar, don't print aka. - if (!AKA) return false; - - // If we did, check to see if we already desugared this type in this - // diagnostic. If so, don't do it again. - for (unsigned i = 0; i != NumPrevArgs; ++i) { - // TODO: Handle ak_declcontext case. - if (PrevArgs[i].first == Diagnostic::ak_qualtype) { - void *Ptr = (void*)PrevArgs[i].second; - QualType PrevTy(QualType::getFromOpaquePtr(Ptr)); - if (PrevTy == InputTy) - return false; - } - } - - DesugaredQT = Qc.apply(QT); - return true; -} - -/// \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, - const Diagnostic::ArgumentValue *PrevArgs, - unsigned NumPrevArgs) { - // FIXME: Playing with std::string is really slow. - std::string S = Ty.getAsString(Context.PrintingPolicy); - - // Consider producing an a.k.a. clause if removing all the direct - // sugar gives us something "significantly different". - - QualType DesugaredTy; - if (ShouldAKA(Context, Ty, PrevArgs, NumPrevArgs, DesugaredTy)) { - 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, - const char *Argument, unsigned ArgLen, - const Diagnostic::ArgumentValue *PrevArgs, - unsigned NumPrevArgs, - llvm::SmallVectorImpl &Output, - void *Cookie) { - ASTContext &Context = *static_cast(Cookie); - - std::string S; - bool NeedQuotes = true; - - switch (Kind) { - default: assert(0 && "unknown ArgumentKind"); - case Diagnostic::ak_qualtype: { - assert(ModLen == 0 && ArgLen == 0 && - "Invalid modifier for QualType argument"); - - QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast(Val))); - S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs); - NeedQuotes = false; - break; - } - case 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) - S = '-' + S; - else - assert(ModLen == 0 && ArgLen == 0 && - "Invalid modifier for DeclarationName argument"); - break; - } - case Diagnostic::ak_nameddecl: { - bool Qualified; - if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0) - Qualified = true; - else { - assert(ModLen == 0 && ArgLen == 0 && - "Invalid modifier for NamedDecl* argument"); - Qualified = false; - } - reinterpret_cast(Val)-> - getNameForDiagnostic(S, Context.PrintingPolicy, Qualified); - break; - } - case Diagnostic::ak_nestednamespec: { - llvm::raw_string_ostream OS(S); - reinterpret_cast(Val)->print(OS, - Context.PrintingPolicy); - NeedQuotes = false; - break; - } - case Diagnostic::ak_declcontext: { - DeclContext *DC = reinterpret_cast (Val); - assert(DC && "Should never have a null declaration context"); - - 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(DC)) { - S = ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type), - PrevArgs, NumPrevArgs); - } else { - // FIXME: Get these strings from some localized place - NamedDecl *ND = cast(DC); - if (isa(ND)) - S += "namespace "; - else if (isa(ND)) - S += "method "; - else if (isa(ND)) - S += "function "; - - S += "'"; - ND->getNameForDiagnostic(S, Context.PrintingPolicy, true); - S += "'"; - } - NeedQuotes = false; - break; - } - } - - if (NeedQuotes) - Output.push_back('\''); - - Output.append(S.begin(), S.end()); - - 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, @@ -363,14 +121,15 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, GlobalNewDeleteDeclared(false), CompleteTranslationUnit(CompleteTranslationUnit), NumSFINAEErrors(0), NonInstantiationEntries(0), - CurrentInstantiationScope(0) + CurrentInstantiationScope(0), TyposCorrected(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); + PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, + &Context); ExprEvalContexts.push_back( ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0)); @@ -426,6 +185,12 @@ void Sema::DeleteStmt(StmtTy *S) { /// popped. void Sema::ActOnEndOfTranslationUnit() { + // Remove functions that turned out to be used. + UnusedStaticFuncs.erase(std::remove_if(UnusedStaticFuncs.begin(), + UnusedStaticFuncs.end(), + std::mem_fun(&FunctionDecl::isUsed)), + UnusedStaticFuncs.end()); + while (1) { // C++: Perform implicit template instantiations. // @@ -472,12 +237,14 @@ 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 (unsigned i = 0, e = TentativeDefinitionList.size(); i != e; ++i) { - VarDecl *VD = TentativeDefinitions.lookup(TentativeDefinitionList[i]); - - // If the tentative definition was completed, it will be in the list, but - // not the map. - if (VD == 0 || VD->isInvalidDecl() || !VD->isTentativeDefinition(Context)) + llvm::SmallSet 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)) continue; if (const IncompleteArrayType *ArrayT @@ -504,6 +271,15 @@ void Sema::ActOnEndOfTranslationUnit() { Consumer.CompleteTentativeDefinition(VD); } + + // Output warning for unused functions. + for (std::vector::iterator + F = UnusedStaticFuncs.begin(), + FEnd = UnusedStaticFuncs.end(); + F != FEnd; + ++F) + Diag((*F)->getLocation(), diag::warn_unused_function) << (*F)->getDeclName(); + } -- cgit v1.1