zcov: / lib/AST/ASTDiagnostic.cpp


Files: 1 Branches Taken: 73.4% 94 / 128
Generated: 2010-02-10 01:31 Branches Executed: 96.9% 124 / 128
Line Coverage: 94.3% 100 / 106


Programs: 2 Runs 3018


       1                 : //===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : //
      10                 : // This file implements a diagnostic formatting hook for AST elements.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : #include "clang/AST/ASTDiagnostic.h"
      14                 : 
      15                 : #include "clang/AST/ASTContext.h"
      16                 : #include "clang/AST/DeclObjC.h"
      17                 : #include "clang/AST/Type.h"
      18                 : #include "llvm/Support/raw_ostream.h"
      19                 : 
      20                 : using namespace clang;
      21                 : 
      22                 : /// Determines whether we should have an a.k.a. clause when
      23                 : /// pretty-printing a type.  There are three main criteria:
      24                 : ///
      25                 : /// 1) Some types provide very minimal sugar that doesn't impede the
      26                 : ///    user's understanding --- for example, elaborated type
      27                 : ///    specifiers.  If this is all the sugar we see, we don't want an
      28                 : ///    a.k.a. clause.
      29                 : /// 2) Some types are technically sugared but are much more familiar
      30                 : ///    when seen in their sugared form --- for example, va_list,
      31                 : ///    vector types, and the magic Objective C types.  We don't
      32                 : ///    want to desugar these, even if we do produce an a.k.a. clause.
      33                 : /// 3) Some types may have already been desugared previously in this diagnostic.
      34                 : ///    if this is the case, doing another "aka" would just be clutter.
      35                 : ///
      36                 : static bool ShouldAKA(ASTContext &Context, QualType QT,
      37                 :                       const Diagnostic::ArgumentValue *PrevArgs,
      38                 :                       unsigned NumPrevArgs,
      39             2968:                       QualType &DesugaredQT) {
      40             2968:   QualType InputTy = QT;
      41                 :   
      42             2968:   bool AKA = false;
      43             2968:   QualifierCollector Qc;
      44                 :   
      45              291:   while (true) {
      46             3259:     const Type *Ty = Qc.strip(QT);
      47                 :     
      48                 :     // Don't aka just because we saw an elaborated type...
                       15: branch 1 taken
                     3244: branch 2 taken
      49             3259:     if (isa<ElaboratedType>(Ty)) {
      50               15:       QT = cast<ElaboratedType>(Ty)->desugar();
      51               15:       continue;
      52                 :     }
      53                 :     
      54                 :     // ...or a qualified name type...
                       27: branch 1 taken
                     3217: branch 2 taken
      55             3244:     if (isa<QualifiedNameType>(Ty)) {
      56               27:       QT = cast<QualifiedNameType>(Ty)->desugar();
      57               27:       continue;
      58                 :     }
      59                 :     
      60                 :     // ...or a substituted template type parameter.
                      155: branch 1 taken
                     3062: branch 2 taken
      61             3217:     if (isa<SubstTemplateTypeParmType>(Ty)) {
      62              155:       QT = cast<SubstTemplateTypeParmType>(Ty)->desugar();
      63              155:       continue;
      64                 :     }
      65                 :     
      66                 :     // Don't desugar template specializations. 
                     3022: branch 1 taken
                       40: branch 2 taken
      67             3062:     if (isa<TemplateSpecializationType>(Ty))
      68               40:       break;
      69                 :     
      70                 :     // Don't desugar magic Objective-C types.
                     3000: branch 3 taken
                       22: branch 4 taken
                     2992: branch 8 taken
                        8: branch 9 taken
                     2992: branch 13 taken
                        0: branch 14 not taken
                        0: branch 18 not taken
                     2992: branch 19 taken
                       30: branch 20 taken
                     2992: branch 21 taken
      71             3022:     if (QualType(Ty,0) == Context.getObjCIdType() ||
      72                 :         QualType(Ty,0) == Context.getObjCClassType() ||
      73                 :         QualType(Ty,0) == Context.getObjCSelType() ||
      74                 :         QualType(Ty,0) == Context.getObjCProtoType())
      75               30:       break;
      76                 :     
      77                 :     // Don't desugar va_list.
                        2: branch 3 taken
                     2990: branch 4 taken
      78             2992:     if (QualType(Ty,0) == Context.getBuiltinVaListType())
      79                2:       break;
      80                 :     
      81                 :     // Otherwise, do a single-step desugar.
      82             2990:     QualType Underlying;
      83             2990:     bool IsSugar = false;
                      819: branch 1 taken
                        3: branch 2 taken
                      488: branch 3 taken
                       41: branch 4 taken
                       71: branch 5 taken
                        5: branch 6 taken
                       42: branch 7 taken
                       42: branch 8 taken
                        5: branch 9 taken
                        0: branch 10 not taken
                        0: branch 11 not taken
                        0: branch 12 not taken
                        9: branch 13 taken
                        0: branch 14 not taken
                       90: branch 15 taken
                        7: branch 16 taken
                        0: branch 17 not taken
                      167: branch 18 taken
                       10: branch 19 taken
                        7: branch 20 taken
                        0: branch 21 not taken
                      933: branch 22 taken
                       19: branch 23 taken
                        0: branch 24 not taken
                        1: branch 25 taken
                        0: branch 26 not taken
                        0: branch 27 not taken
                        0: branch 28 not taken
                        0: branch 29 not taken
                       28: branch 30 taken
                      203: branch 31 taken
                        0: branch 32 not taken
      84             2990:     switch (Ty->getTypeClass()) {
      85                 : #define ABSTRACT_TYPE(Class, Base)
      86                 : #define TYPE(Class, Base) \
      87                 : case Type::Class: { \
      88                 : const Class##Type *CTy = cast<Class##Type>(Ty); \
      89                 : if (CTy->isSugared()) { \
      90                 : IsSugar = true; \
      91                 : Underlying = CTy->desugar(); \
      92                 : } \
      93                 : break; \
      94                 : }
      95                 : #include "clang/AST/TypeNodes.def"
      96                 :     }
      97                 :     
      98                 :     // If it wasn't sugared, we're done.
                     2806: branch 0 taken
                      184: branch 1 taken
      99             2990:     if (!IsSugar)
     100             2806:       break;
     101                 :     
     102                 :     // If the desugared type is a vector type, we don't want to expand
     103                 :     // it, it will turn into an attribute mess. People want their "vec4".
                       86: branch 1 taken
                       98: branch 2 taken
     104              184:     if (isa<VectorType>(Underlying))
     105               86:       break;
     106                 :     
     107                 :     // Don't desugar through the primary typedef of an anonymous type.
                        8: branch 1 taken
                       90: branch 2 taken
                        7: branch 4 taken
                        1: branch 5 taken
                        7: branch 6 taken
                       91: branch 7 taken
     108               98:     if (isa<TagType>(Underlying) && isa<TypedefType>(QT))
                        4: branch 5 taken
                        3: branch 6 taken
     109                7:       if (cast<TagType>(Underlying)->getDecl()->getTypedefForAnonDecl() ==
     110                 :           cast<TypedefType>(QT)->getDecl())
     111                4:         break;
     112                 :     
     113                 :     // Otherwise, we're tearing through something opaque; note that
     114                 :     // we'll eventually need an a.k.a. clause and keep going.
     115               94:     AKA = true;
     116               94:     QT = Underlying;
     117                 :     continue;
     118                 :   }
     119                 :   
     120                 :   // If we never tore through opaque sugar, don't print aka.
                     2890: branch 0 taken
                       78: branch 1 taken
     121             2968:   if (!AKA) return false;
     122                 :   
     123                 :   // If we did, check to see if we already desugared this type in this
     124                 :   // diagnostic.  If so, don't do it again.
                       72: branch 0 taken
                       77: branch 1 taken
     125              149:   for (unsigned i = 0; i != NumPrevArgs; ++i) {
     126                 :     // TODO: Handle ak_declcontext case.
                       24: branch 0 taken
                       48: branch 1 taken
     127               72:     if (PrevArgs[i].first == Diagnostic::ak_qualtype) {
     128               24:       void *Ptr = (void*)PrevArgs[i].second;
     129               24:       QualType PrevTy(QualType::getFromOpaquePtr(Ptr));
                        1: branch 1 taken
                       23: branch 2 taken
     130               24:       if (PrevTy == InputTy)
     131                1:         return false;
     132                 :     }
     133                 :   }
     134                 :   
     135               77:   DesugaredQT = Qc.apply(QT);
     136               77:   return true;
     137                 : }
     138                 : 
     139                 : /// \brief Convert the given type to a string suitable for printing as part of 
     140                 : /// a diagnostic. 
     141                 : ///
     142                 : /// \param Context the context in which the type was allocated
     143                 : /// \param Ty the type to print
     144                 : static std::string
     145                 : ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
     146                 :                               const Diagnostic::ArgumentValue *PrevArgs,
     147             2968:                               unsigned NumPrevArgs) {
     148                 :   // FIXME: Playing with std::string is really slow.
     149             2968:   std::string S = Ty.getAsString(Context.PrintingPolicy);
     150                 :   
     151                 :   // Consider producing an a.k.a. clause if removing all the direct
     152                 :   // sugar gives us something "significantly different".
     153                 :   
     154             2968:   QualType DesugaredTy;
                       77: branch 1 taken
                     2891: branch 2 taken
     155             2968:   if (ShouldAKA(Context, Ty, PrevArgs, NumPrevArgs, DesugaredTy)) {
     156               77:     S = "'"+S+"' (aka '";
     157               77:     S += DesugaredTy.getAsString(Context.PrintingPolicy);
     158               77:     S += "')";
     159               77:     return S;
     160                 :   }
     161                 :   
     162             2891:   S = "'" + S + "'";
     163             2891:   return S;
     164                 : }
     165                 : 
     166                 : void clang::FormatASTNodeDiagnosticArgument(Diagnostic::ArgumentKind Kind, 
     167                 :                                             intptr_t Val,
     168                 :                                             const char *Modifier, 
     169                 :                                             unsigned ModLen,
     170                 :                                             const char *Argument, 
     171                 :                                             unsigned ArgLen,
     172                 :                                     const Diagnostic::ArgumentValue *PrevArgs,
     173                 :                                             unsigned NumPrevArgs,
     174                 :                                             llvm::SmallVectorImpl<char> &Output,
     175             4577:                                             void *Cookie) {
     176             4577:   ASTContext &Context = *static_cast<ASTContext*>(Cookie);
     177                 :   
     178             4577:   std::string S;
     179             4577:   bool NeedQuotes = true;
     180                 :   
                        0: branch 0 not taken
                     2903: branch 1 taken
                     1261: branch 2 taken
                      308: branch 3 taken
                       17: branch 4 taken
                       88: branch 5 taken
     181             4577:   switch (Kind) {
     182                0:     default: assert(0 && "unknown ArgumentKind");
     183                 :     case Diagnostic::ak_qualtype: {
     184                 :       assert(ModLen == 0 && ArgLen == 0 &&
                     2903: branch 0 taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                     2903: branch 3 taken
     185             2903:              "Invalid modifier for QualType argument");
     186                 :       
     187             2903:       QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));
     188             2903:       S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs);
     189             2903:       NeedQuotes = false;
     190             2903:       break;
     191                 :     }
     192                 :     case Diagnostic::ak_declarationname: {
     193             1261:       DeclarationName N = DeclarationName::getFromOpaqueInteger(Val);
     194             1261:       S = N.getAsString();
     195                 :       
                       24: branch 0 taken
                     1237: branch 1 taken
                       24: branch 3 taken
                        0: branch 4 not taken
                       24: branch 5 taken
                        0: branch 6 not taken
     196             1285:       if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0)
     197               24:         S = '+' + S;
                       64: branch 0 taken
                     1173: branch 1 taken
                       64: branch 3 taken
                        0: branch 4 not taken
                       64: branch 5 taken
                        0: branch 6 not taken
     198             1301:       else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12)
     199                 :                 && ArgLen==0)
     200               64:         S = '-' + S;
     201                 :       else
     202                 :         assert(ModLen == 0 && ArgLen == 0 &&
                     1173: branch 0 taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                     1173: branch 3 taken
     203             1173:                "Invalid modifier for DeclarationName argument");
     204             1261:       break;
     205                 :     }
     206                 :     case Diagnostic::ak_nameddecl: {
     207                 :       bool Qualified;
                      171: branch 0 taken
                      137: branch 1 taken
                      171: branch 2 taken
                        0: branch 3 not taken
                      171: branch 4 taken
                        0: branch 5 not taken
     208              479:       if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0)
     209              171:         Qualified = true;
     210                 :       else {
     211                 :         assert(ModLen == 0 && ArgLen == 0 &&
                      137: branch 0 taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                      137: branch 3 taken
     212              137:                "Invalid modifier for NamedDecl* argument");
     213              137:         Qualified = false;
     214                 :       }
     215                 :       reinterpret_cast<NamedDecl*>(Val)->
     216              308:       getNameForDiagnostic(S, Context.PrintingPolicy, Qualified);
     217              308:       break;
     218                 :     }
     219                 :     case Diagnostic::ak_nestednamespec: {
     220               17:       llvm::raw_string_ostream OS(S);
     221                 :       reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS,
     222               17:                                                         Context.PrintingPolicy);
     223               17:       NeedQuotes = false;
     224               17:       break;
     225                 :     }
     226                 :     case Diagnostic::ak_declcontext: {
     227               88:       DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
                        0: branch 0 not taken
                       88: branch 1 taken
     228               88:       assert(DC && "Should never have a null declaration context");
     229                 :       
                        5: branch 1 taken
                       83: branch 2 taken
     230               88:       if (DC->isTranslationUnit()) {
     231                 :         // FIXME: Get these strings from some localized place
                        5: branch 1 taken
                        0: branch 2 not taken
     232                5:         if (Context.getLangOptions().CPlusPlus)
     233                5:           S = "the global namespace";
     234                 :         else
     235                0:           S = "the global scope";
                       65: branch 1 taken
                       18: branch 2 taken
     236               83:       } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) {
     237                 :         S = ConvertTypeToDiagnosticString(Context, 
     238                 :                                           Context.getTypeDeclType(Type),
     239               65:                                           PrevArgs, NumPrevArgs);
     240                 :       } else {
     241                 :         // FIXME: Get these strings from some localized place
     242               18:         NamedDecl *ND = cast<NamedDecl>(DC);
                       18: branch 1 taken
                        0: branch 2 not taken
     243               18:         if (isa<NamespaceDecl>(ND))
     244               18:           S += "namespace ";
                        0: branch 1 not taken
                        0: branch 2 not taken
     245                0:         else if (isa<ObjCMethodDecl>(ND))
     246                0:           S += "method ";
                        0: branch 1 not taken
                        0: branch 2 not taken
     247                0:         else if (isa<FunctionDecl>(ND))
     248                0:           S += "function ";
     249                 :         
     250               18:         S += "'";
     251               18:         ND->getNameForDiagnostic(S, Context.PrintingPolicy, true);
     252               18:         S += "'";
     253                 :       }
     254               88:       NeedQuotes = false;
     255                 :       break;
     256                 :     }
     257                 :   }
     258                 :   
                     1569: branch 0 taken
                     3008: branch 1 taken
     259             4577:   if (NeedQuotes)
     260             1569:     Output.push_back('\'');
     261                 :   
     262             4577:   Output.append(S.begin(), S.end());
     263                 :   
                     1569: branch 0 taken
                     3008: branch 1 taken
     264             4577:   if (NeedQuotes)
     265             1569:     Output.push_back('\'');
     266             4577: }

Generated: 2010-02-10 01:31 by zcov