From: Chris Lattner Date: Sun, 23 Nov 2008 20:28:15 +0000 (+0000) Subject: add support for inserting a DeclarationName into a diagnostic directly X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=011bb4edf731d529da1cbf71c7c2696aaf5a054f;p=clang add support for inserting a DeclarationName into a diagnostic directly without calling getAsString(). This implicitly puts quotes around the name, so diagnostics need to be tweaked to accommodate this. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59916 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 4c7a17096e..f387d69986 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -22,11 +22,11 @@ namespace llvm { } namespace clang { - class CXXSpecialName; // a private class used by DeclarationName - class CXXOperatorIdName; // a private class used by DeclarationName - class DeclarationNameExtra; // a private class used by DeclarationName + class CXXSpecialName; + class CXXOperatorIdName; + class DeclarationNameExtra; class IdentifierInfo; - class MultiKeywordSelector; // a private class used by Selector and DeclarationName + class MultiKeywordSelector; /// DeclarationName - The name of a declaration. In the common case, /// this just stores an IdentifierInfo pointer to a normal @@ -198,6 +198,12 @@ public: /// name as an opaque integer. uintptr_t getAsOpaqueInteger() const { return Ptr; } + static DeclarationName getFromOpaqueInteger(uintptr_t P) { + DeclarationName N; + N.Ptr = P; + return N; + } + /// getCXXNameType - If this name is one of the C++ names (of a /// constructor, destructor, or conversion function), return the /// type associated with that name. @@ -314,6 +320,16 @@ public: DeclarationName getCXXOperatorName(OverloadedOperatorKind Op); }; +/// Insertion operator for diagnostics. This allows sending DeclarationName's +/// into a diagnostic with <<. +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + DeclarationName N) { + DB.AddTaggedVal(N.getAsOpaqueInteger(), + Diagnostic::ak_declarationname); + return DB; +} + + } // end namespace clang namespace llvm { diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index ed1e33752d..a8e1bcbd1e 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1494,7 +1494,6 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, Diagnostic::ak_qualtype); return DB; } - } // end namespace clang diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h index 945cca3ed0..d62fe61f71 100644 --- a/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/include/clang/Analysis/PathSensitive/BugReporter.h @@ -335,7 +335,8 @@ public: case Diagnostic::ak_identifierinfo: R.addString(Info.getArgIdentifier(i)->getName()); break; - case Diagnostic::ak_qualtype: { + case Diagnostic::ak_qualtype: + case Diagnostic::ak_declarationname: { llvm::SmallString<64> Str; Info.getDiags()->ConvertArgToString(Info.getArgKind(i), Info.getRawArg(i), 0, 0, 0, 0, Str); diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 144095f129..430e0c4266 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -68,7 +68,8 @@ public: ak_sint, // int ak_uint, // unsigned ak_identifierinfo, // IdentifierInfo - ak_qualtype // QualType + ak_qualtype, // QualType + ak_declarationname // DeclarationName }; private: diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index e33e6562b3..1f15366fbb 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -1218,9 +1218,9 @@ DIAG(err_typecheck_bool_condition, ERROR, DIAG(err_expected_class_or_namespace, ERROR, "expected a class or namespace") DIAG(err_invalid_declarator_scope, ERROR, - "definition or redeclaration for '%0' not in a namespace enclosing '%1'") + "definition or redeclaration of '%0' not in a namespace enclosing '%1'") DIAG(err_invalid_declarator_in_function, ERROR, - "definition or redeclaration for '%0' not allowed inside a function") + "definition or redeclaration of %0 not allowed inside a function") DIAG(err_not_tag_in_scope, ERROR, "'%0' does not name a tag member in the specified scope") diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp index fd65f75e08..efdb329171 100644 --- a/lib/Basic/Diagnostic.cpp +++ b/lib/Basic/Diagnostic.cpp @@ -536,6 +536,7 @@ FormatDiagnostic(llvm::SmallVectorImpl &OutStr) const { break; } case Diagnostic::ak_qualtype: + case Diagnostic::ak_declarationname: OutStr.push_back('\''); getDiags()->ConvertArgToString(getArgKind(ArgNo), getRawArg(ArgNo), Modifier, ModifierLen, diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index b01b5d77f3..be21c36073 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -22,17 +22,24 @@ using namespace clang; /// ConvertQualTypeToStringFn - This function is used to pretty print the /// specified QualType as a string in diagnostics. -static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t QT, +static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val, const char *Modifier, unsigned ML, const char *Argument, unsigned ArgLen, llvm::SmallVectorImpl &Output) { assert(ML == 0 && ArgLen == 0 && "Invalid modifier for QualType argument"); - assert(Kind == Diagnostic::ak_qualtype); - QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast(QT))); + std::string S; + if (Kind == Diagnostic::ak_qualtype) { + QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast(Val))); - // FIXME: Playing with std::string is really slow. - std::string S = Ty.getAsString(); + // FIXME: Playing with std::string is really slow. + S = Ty.getAsString(); + } else { + assert(Kind == Diagnostic::ak_declarationname); + + DeclarationName N = DeclarationName::getFromOpaqueInteger(Val); + S = N.getAsString(); + } Output.append(S.begin(), S.end()); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index ef24d1a34a..fba9f3328b 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -856,10 +856,9 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) { SourceLocation L = D.getIdentifierLoc(); SourceRange R = D.getCXXScopeSpec().getRange(); if (isa(CurContext)) { - Diag(L, diag::err_invalid_declarator_in_function) - << Name.getAsString() << R; + Diag(L, diag::err_invalid_declarator_in_function) << Name << R; } else { - Diag(L, diag::err_invalid_declarator_scope) + Diag(L, diag::err_invalid_declarator_scope) << Name.getAsString() << cast(DC)->getName() << R; } } diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp index 18cb3b418a..8e7e17af9d 100644 --- a/test/SemaCXX/nested-name-spec.cpp +++ b/test/SemaCXX/nested-name-spec.cpp @@ -21,11 +21,11 @@ void C2::m() { } namespace B { - void ::A::Af() {} // expected-error {{definition or redeclaration for 'Af' not in a namespace enclosing 'A'}} + void ::A::Af() {} // expected-error {{definition or redeclaration of 'Af' not in a namespace enclosing 'A'}} } void f1() { - void A::Af(); // expected-error {{definition or redeclaration for 'Af' not allowed inside a function}} + void A::Af(); // expected-error {{definition or redeclaration of 'Af' not allowed inside a function}} } void f2() {