summaryrefslogtreecommitdiffstats
path: root/lib/Sema/Sema.cpp
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2009-10-23 14:22:18 +0000
committerrdivacky <rdivacky@FreeBSD.org>2009-10-23 14:22:18 +0000
commit5563df30b9c8d1fe87a54baae0d6bd86642563f4 (patch)
tree3fdd91eae574e32453a4baf462961c742df2691a /lib/Sema/Sema.cpp
parente5557c18e5d41b4b62f2af8a24af20eba40b0225 (diff)
downloadFreeBSD-src-5563df30b9c8d1fe87a54baae0d6bd86642563f4.zip
FreeBSD-src-5563df30b9c8d1fe87a54baae0d6bd86642563f4.tar.gz
Update clang to r84949.
Diffstat (limited to 'lib/Sema/Sema.cpp')
-rw-r--r--lib/Sema/Sema.cpp207
1 files changed, 153 insertions, 54 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index ba05a07..fc9c14f 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -23,44 +23,134 @@
#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;
+
+ // 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) {
+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);
- // If this is a sugared type (like a typedef, typeof, etc), then unwrap one
- // level of the sugar so that the type is more obvious to the user.
- QualType DesugaredTy = Ty.getDesugaredType();
-
- if (Ty != DesugaredTy &&
- // 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".
- !isa<VectorType>(DesugaredTy) &&
-
- // Don't aka just because we saw an elaborated type...
- (!isa<ElaboratedType>(Ty) ||
- cast<ElaboratedType>(Ty)->desugar() != DesugaredTy) &&
-
- // ...or a qualified name type...
- (!isa<QualifiedNameType>(Ty) ||
- cast<QualifiedNameType>(Ty)->desugar() != DesugaredTy) &&
-
- // ...or a non-dependent template specialization.
- (!isa<TemplateSpecializationType>(Ty) || Ty->isDependentType()) &&
-
- // Don't desugar magic Objective-C types.
- Ty.getUnqualifiedType() != Context.getObjCIdType() &&
- Ty.getUnqualifiedType() != Context.getObjCClassType() &&
- Ty.getUnqualifiedType() != Context.getObjCSelType() &&
- Ty.getUnqualifiedType() != Context.getObjCProtoType() &&
-
- // Not va_list.
- Ty.getUnqualifiedType() != Context.getBuiltinVaListType()) {
+ // 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 += "')";
@@ -76,21 +166,27 @@ static std::string ConvertTypeToDiagnosticString(ASTContext &Context,
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;
- if (Kind == Diagnostic::ak_qualtype) {
+
+ 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);
+ S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs);
NeedQuotes = false;
- } else if (Kind == Diagnostic::ak_declarationname) {
-
+ break;
+ }
+ case Diagnostic::ak_declarationname: {
DeclarationName N = DeclarationName::getFromOpaqueInteger(Val);
S = N.getAsString();
@@ -101,7 +197,9 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
else
assert(ModLen == 0 && ArgLen == 0 &&
"Invalid modifier for DeclarationName argument");
- } else if (Kind == Diagnostic::ak_nameddecl) {
+ break;
+ }
+ case Diagnostic::ak_nameddecl: {
bool Qualified;
if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0)
Qualified = true;
@@ -110,30 +208,30 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
"Invalid modifier for NamedDecl* argument");
Qualified = false;
}
- reinterpret_cast<NamedDecl*>(Val)->getNameForDiagnostic(S,
- Context.PrintingPolicy,
- Qualified);
- } else if (Kind == Diagnostic::ak_nestednamespec) {
+ 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);
+ reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS,
+ Context.PrintingPolicy);
NeedQuotes = false;
- } else {
- assert(Kind == Diagnostic::ak_declcontext);
+ break;
+ }
+ case Diagnostic::ak_declcontext: {
DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
- NeedQuotes = false;
- if (!DC) {
- assert(false && "Should never have a null declaration context");
- S = "unknown context";
- } else if (DC->isTranslationUnit()) {
+ 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));
- NeedQuotes = false;
+ S = ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type),
+ PrevArgs, NumPrevArgs);
} else {
// FIXME: Get these strings from some localized place
NamedDecl *ND = cast<NamedDecl>(DC);
@@ -147,8 +245,10 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
S += "'";
ND->getNameForDiagnostic(S, Context.PrintingPolicy, true);
S += "'";
- NeedQuotes = false;
}
+ NeedQuotes = false;
+ break;
+ }
}
if (NeedQuotes)
@@ -361,9 +461,8 @@ void Sema::ActOnEndOfTranslationUnit() {
// Set the length of the array to 1 (C99 6.9.2p5).
Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
- QualType T
- = Context.getConstantArrayWithoutExprType(ArrayT->getElementType(),
- One, ArrayType::Normal, 0);
+ QualType T = Context.getConstantArrayType(ArrayT->getElementType(),
+ One, ArrayType::Normal, 0);
VD->setType(T);
} else if (RequireCompleteType(VD->getLocation(), VD->getType(),
diag::err_tentative_def_incomplete_type))
OpenPOWER on IntegriCloud