diff options
Diffstat (limited to 'lib/Sema/Sema.cpp')
-rw-r--r-- | lib/Sema/Sema.cpp | 248 |
1 files changed, 3 insertions, 245 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 903b987080..e9a1d9c5fc 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -19,257 +19,14 @@ #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<ElaboratedType>(Ty)) { - QT = cast<ElaboratedType>(Ty)->desugar(); - continue; - } - - // ...or a qualified name type... - if (isa<QualifiedNameType>(Ty)) { - QT = cast<QualifiedNameType>(Ty)->desugar(); - continue; - } - - // ...or a substituted template type parameter. - if (isa<SubstTemplateTypeParmType>(Ty)) { - QT = cast<SubstTemplateTypeParmType>(Ty)->desugar(); - continue; - } - - // Don't desugar template specializations. - if (isa<TemplateSpecializationType>(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<Class##Type>(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<VectorType>(Underlying)) - break; - - // Don't desugar through the primary typedef of an anonymous type. - if (isa<TagType>(Underlying) && isa<TypedefType>(QT)) - if (cast<TagType>(Underlying)->getDecl()->getTypedefForAnonDecl() == - cast<TypedefType>(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<char> &Output, - void *Cookie) { - ASTContext &Context = *static_cast<ASTContext*>(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<void*>(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<NamedDecl*>(Val)-> - getNameForDiagnostic(S, Context.PrintingPolicy, Qualified); - break; - } - case Diagnostic::ak_nestednamespec: { - llvm::raw_string_ostream OS(S); - reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS, - Context.PrintingPolicy); - NeedQuotes = false; - break; - } - case Diagnostic::ak_declcontext: { - DeclContext *DC = reinterpret_cast<DeclContext *> (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<TypeDecl>(DC)) { - S = ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type), - PrevArgs, NumPrevArgs); - } 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; - 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, @@ -371,7 +128,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, 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)); |