clang API Documentation
00001 //===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements a diagnostic formatting hook for AST elements. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 #include "clang/AST/ASTDiagnostic.h" 00014 00015 #include "clang/AST/ASTContext.h" 00016 #include "clang/AST/DeclObjC.h" 00017 #include "clang/AST/Type.h" 00018 #include "llvm/Support/raw_ostream.h" 00019 00020 using namespace clang; 00021 00022 // Returns a desugared version of the QualType, and marks ShouldAKA as true 00023 // whenever we remove significant sugar from the type. 00024 static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { 00025 QualifierCollector QC; 00026 00027 while (true) { 00028 const Type *Ty = QC.strip(QT); 00029 00030 // Don't aka just because we saw an elaborated type... 00031 if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty)) { 00032 QT = ET->desugar(); 00033 continue; 00034 } 00035 // ... or a paren type ... 00036 if (const ParenType *PT = dyn_cast<ParenType>(Ty)) { 00037 QT = PT->desugar(); 00038 continue; 00039 } 00040 // ...or a substituted template type parameter ... 00041 if (const SubstTemplateTypeParmType *ST = 00042 dyn_cast<SubstTemplateTypeParmType>(Ty)) { 00043 QT = ST->desugar(); 00044 continue; 00045 } 00046 // ...or an attributed type... 00047 if (const AttributedType *AT = dyn_cast<AttributedType>(Ty)) { 00048 QT = AT->desugar(); 00049 continue; 00050 } 00051 // ... or an auto type. 00052 if (const AutoType *AT = dyn_cast<AutoType>(Ty)) { 00053 if (!AT->isSugared()) 00054 break; 00055 QT = AT->desugar(); 00056 continue; 00057 } 00058 00059 // Don't desugar template specializations, unless it's an alias template. 00060 if (const TemplateSpecializationType *TST 00061 = dyn_cast<TemplateSpecializationType>(Ty)) 00062 if (!TST->isTypeAlias()) 00063 break; 00064 00065 // Don't desugar magic Objective-C types. 00066 if (QualType(Ty,0) == Context.getObjCIdType() || 00067 QualType(Ty,0) == Context.getObjCClassType() || 00068 QualType(Ty,0) == Context.getObjCSelType() || 00069 QualType(Ty,0) == Context.getObjCProtoType()) 00070 break; 00071 00072 // Don't desugar va_list. 00073 if (QualType(Ty,0) == Context.getBuiltinVaListType()) 00074 break; 00075 00076 // Otherwise, do a single-step desugar. 00077 QualType Underlying; 00078 bool IsSugar = false; 00079 switch (Ty->getTypeClass()) { 00080 #define ABSTRACT_TYPE(Class, Base) 00081 #define TYPE(Class, Base) \ 00082 case Type::Class: { \ 00083 const Class##Type *CTy = cast<Class##Type>(Ty); \ 00084 if (CTy->isSugared()) { \ 00085 IsSugar = true; \ 00086 Underlying = CTy->desugar(); \ 00087 } \ 00088 break; \ 00089 } 00090 #include "clang/AST/TypeNodes.def" 00091 } 00092 00093 // If it wasn't sugared, we're done. 00094 if (!IsSugar) 00095 break; 00096 00097 // If the desugared type is a vector type, we don't want to expand 00098 // it, it will turn into an attribute mess. People want their "vec4". 00099 if (isa<VectorType>(Underlying)) 00100 break; 00101 00102 // Don't desugar through the primary typedef of an anonymous type. 00103 if (const TagType *UTT = Underlying->getAs<TagType>()) 00104 if (const TypedefType *QTT = dyn_cast<TypedefType>(QT)) 00105 if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl()) 00106 break; 00107 00108 // Record that we actually looked through an opaque type here. 00109 ShouldAKA = true; 00110 QT = Underlying; 00111 } 00112 00113 // If we have a pointer-like type, desugar the pointee as well. 00114 // FIXME: Handle other pointer-like types. 00115 if (const PointerType *Ty = QT->getAs<PointerType>()) { 00116 QT = Context.getPointerType(Desugar(Context, Ty->getPointeeType(), 00117 ShouldAKA)); 00118 } else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) { 00119 QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(), 00120 ShouldAKA)); 00121 } else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) { 00122 QT = Context.getRValueReferenceType(Desugar(Context, Ty->getPointeeType(), 00123 ShouldAKA)); 00124 } 00125 00126 return QC.apply(Context, QT); 00127 } 00128 00129 /// \brief Convert the given type to a string suitable for printing as part of 00130 /// a diagnostic. 00131 /// 00132 /// There are four main criteria when determining whether we should have an 00133 /// a.k.a. clause when pretty-printing a type: 00134 /// 00135 /// 1) Some types provide very minimal sugar that doesn't impede the 00136 /// user's understanding --- for example, elaborated type 00137 /// specifiers. If this is all the sugar we see, we don't want an 00138 /// a.k.a. clause. 00139 /// 2) Some types are technically sugared but are much more familiar 00140 /// when seen in their sugared form --- for example, va_list, 00141 /// vector types, and the magic Objective C types. We don't 00142 /// want to desugar these, even if we do produce an a.k.a. clause. 00143 /// 3) Some types may have already been desugared previously in this diagnostic. 00144 /// if this is the case, doing another "aka" would just be clutter. 00145 /// 4) Two different types within the same diagnostic have the same output 00146 /// string. In this case, force an a.k.a with the desugared type when 00147 /// doing so will provide additional information. 00148 /// 00149 /// \param Context the context in which the type was allocated 00150 /// \param Ty the type to print 00151 /// \param QualTypeVals pointer values to QualTypes which are used in the 00152 /// diagnostic message 00153 static std::string 00154 ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, 00155 const DiagnosticsEngine::ArgumentValue *PrevArgs, 00156 unsigned NumPrevArgs, 00157 ArrayRef<intptr_t> QualTypeVals) { 00158 // FIXME: Playing with std::string is really slow. 00159 bool ForceAKA = false; 00160 QualType CanTy = Ty.getCanonicalType(); 00161 std::string S = Ty.getAsString(Context.getPrintingPolicy()); 00162 std::string CanS = CanTy.getAsString(Context.getPrintingPolicy()); 00163 00164 for (unsigned I = 0, E = QualTypeVals.size(); I != E; ++I) { 00165 QualType CompareTy = 00166 QualType::getFromOpaquePtr(reinterpret_cast<void*>(QualTypeVals[I])); 00167 if (CompareTy.isNull()) 00168 continue; 00169 if (CompareTy == Ty) 00170 continue; // Same types 00171 QualType CompareCanTy = CompareTy.getCanonicalType(); 00172 if (CompareCanTy == CanTy) 00173 continue; // Same canonical types 00174 std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy()); 00175 bool aka; 00176 QualType CompareDesugar = Desugar(Context, CompareTy, aka); 00177 std::string CompareDesugarStr = 00178 CompareDesugar.getAsString(Context.getPrintingPolicy()); 00179 if (CompareS != S && CompareDesugarStr != S) 00180 continue; // The type string is different than the comparison string 00181 // and the desugared comparison string. 00182 std::string CompareCanS = 00183 CompareCanTy.getAsString(Context.getPrintingPolicy()); 00184 00185 if (CompareCanS == CanS) 00186 continue; // No new info from canonical type 00187 00188 ForceAKA = true; 00189 break; 00190 } 00191 00192 // Check to see if we already desugared this type in this 00193 // diagnostic. If so, don't do it again. 00194 bool Repeated = false; 00195 for (unsigned i = 0; i != NumPrevArgs; ++i) { 00196 // TODO: Handle ak_declcontext case. 00197 if (PrevArgs[i].first == DiagnosticsEngine::ak_qualtype) { 00198 void *Ptr = (void*)PrevArgs[i].second; 00199 QualType PrevTy(QualType::getFromOpaquePtr(Ptr)); 00200 if (PrevTy == Ty) { 00201 Repeated = true; 00202 break; 00203 } 00204 } 00205 } 00206 00207 // Consider producing an a.k.a. clause if removing all the direct 00208 // sugar gives us something "significantly different". 00209 if (!Repeated) { 00210 bool ShouldAKA = false; 00211 QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA); 00212 if (ShouldAKA || ForceAKA) { 00213 if (DesugaredTy == Ty) { 00214 DesugaredTy = Ty.getCanonicalType(); 00215 } 00216 std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy()); 00217 if (akaStr != S) { 00218 S = "'" + S + "' (aka '" + akaStr + "')"; 00219 return S; 00220 } 00221 } 00222 } 00223 00224 S = "'" + S + "'"; 00225 return S; 00226 } 00227 00228 void clang::FormatASTNodeDiagnosticArgument( 00229 DiagnosticsEngine::ArgumentKind Kind, 00230 intptr_t Val, 00231 const char *Modifier, 00232 unsigned ModLen, 00233 const char *Argument, 00234 unsigned ArgLen, 00235 const DiagnosticsEngine::ArgumentValue *PrevArgs, 00236 unsigned NumPrevArgs, 00237 SmallVectorImpl<char> &Output, 00238 void *Cookie, 00239 ArrayRef<intptr_t> QualTypeVals) { 00240 ASTContext &Context = *static_cast<ASTContext*>(Cookie); 00241 00242 std::string S; 00243 bool NeedQuotes = true; 00244 00245 switch (Kind) { 00246 default: llvm_unreachable("unknown ArgumentKind"); 00247 case DiagnosticsEngine::ak_qualtype: { 00248 assert(ModLen == 0 && ArgLen == 0 && 00249 "Invalid modifier for QualType argument"); 00250 00251 QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val))); 00252 S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs, 00253 QualTypeVals); 00254 NeedQuotes = false; 00255 break; 00256 } 00257 case DiagnosticsEngine::ak_declarationname: { 00258 DeclarationName N = DeclarationName::getFromOpaqueInteger(Val); 00259 S = N.getAsString(); 00260 00261 if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0) 00262 S = '+' + S; 00263 else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12) 00264 && ArgLen==0) 00265 S = '-' + S; 00266 else 00267 assert(ModLen == 0 && ArgLen == 0 && 00268 "Invalid modifier for DeclarationName argument"); 00269 break; 00270 } 00271 case DiagnosticsEngine::ak_nameddecl: { 00272 bool Qualified; 00273 if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0) 00274 Qualified = true; 00275 else { 00276 assert(ModLen == 0 && ArgLen == 0 && 00277 "Invalid modifier for NamedDecl* argument"); 00278 Qualified = false; 00279 } 00280 const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val); 00281 ND->getNameForDiagnostic(S, Context.getPrintingPolicy(), Qualified); 00282 break; 00283 } 00284 case DiagnosticsEngine::ak_nestednamespec: { 00285 llvm::raw_string_ostream OS(S); 00286 reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS, 00287 Context.getPrintingPolicy()); 00288 NeedQuotes = false; 00289 break; 00290 } 00291 case DiagnosticsEngine::ak_declcontext: { 00292 DeclContext *DC = reinterpret_cast<DeclContext *> (Val); 00293 assert(DC && "Should never have a null declaration context"); 00294 00295 if (DC->isTranslationUnit()) { 00296 // FIXME: Get these strings from some localized place 00297 if (Context.getLangOpts().CPlusPlus) 00298 S = "the global namespace"; 00299 else 00300 S = "the global scope"; 00301 } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) { 00302 S = ConvertTypeToDiagnosticString(Context, 00303 Context.getTypeDeclType(Type), 00304 PrevArgs, NumPrevArgs, QualTypeVals); 00305 } else { 00306 // FIXME: Get these strings from some localized place 00307 NamedDecl *ND = cast<NamedDecl>(DC); 00308 if (isa<NamespaceDecl>(ND)) 00309 S += "namespace "; 00310 else if (isa<ObjCMethodDecl>(ND)) 00311 S += "method "; 00312 else if (isa<FunctionDecl>(ND)) 00313 S += "function "; 00314 00315 S += "'"; 00316 ND->getNameForDiagnostic(S, Context.getPrintingPolicy(), true); 00317 S += "'"; 00318 } 00319 NeedQuotes = false; 00320 break; 00321 } 00322 } 00323 00324 if (NeedQuotes) 00325 Output.push_back('\''); 00326 00327 Output.append(S.begin(), S.end()); 00328 00329 if (NeedQuotes) 00330 Output.push_back('\''); 00331 }