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.

llvm-svn: 59916
This commit is contained in:
Chris Lattner 2008-11-23 20:28:15 +00:00
parent d125393d24
commit f7e69d5a77
9 changed files with 43 additions and 19 deletions

View File

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

View File

@ -1494,7 +1494,6 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
Diagnostic::ak_qualtype);
return DB;
}
} // end namespace clang

View File

@ -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);

View File

@ -68,7 +68,8 @@ public:
ak_sint, // int
ak_uint, // unsigned
ak_identifierinfo, // IdentifierInfo
ak_qualtype // QualType
ak_qualtype, // QualType
ak_declarationname // DeclarationName
};
private:

View File

@ -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")

View File

@ -536,6 +536,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
break;
}
case Diagnostic::ak_qualtype:
case Diagnostic::ak_declarationname:
OutStr.push_back('\'');
getDiags()->ConvertArgToString(getArgKind(ArgNo), getRawArg(ArgNo),
Modifier, ModifierLen,

View File

@ -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<char> &Output) {
assert(ML == 0 && ArgLen == 0 && "Invalid modifier for QualType argument");
assert(Kind == Diagnostic::ak_qualtype);
QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(QT)));
std::string S;
if (Kind == Diagnostic::ak_qualtype) {
QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(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());
}

View File

@ -856,10 +856,9 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
SourceLocation L = D.getIdentifierLoc();
SourceRange R = D.getCXXScopeSpec().getRange();
if (isa<FunctionDecl>(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<NamedDecl>(DC)->getName() << R;
}
}

View File

@ -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() {