 |
|
 |
|
| 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 |
| |
 |
|
 |
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