mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 12:26:52 +08:00
Unify our diagnostic printing for errors of the form, "we didn't like
what we found when we looked into <blah>", where <blah> is a DeclContext*. We can now format DeclContext*'s in nice ways, e.g., "namespace N", "the global namespace", "'class Foo'". This is part of PR3990, but we're not quite there yet. llvm-svn: 84028
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#define LLVM_CLANG_DIAGNOSTIC_H
|
||||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/Support/type_traits.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
@@ -24,6 +25,7 @@ namespace llvm {
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
class DeclContext;
|
||||
class DiagnosticBuilder;
|
||||
class DiagnosticClient;
|
||||
class IdentifierInfo;
|
||||
@@ -158,7 +160,8 @@ public:
|
||||
ak_qualtype, // QualType
|
||||
ak_declarationname, // DeclarationName
|
||||
ak_nameddecl, // NamedDecl *
|
||||
ak_nestednamespec // NestedNameSpecifier *
|
||||
ak_nestednamespec, // NestedNameSpecifier *
|
||||
ak_declcontext // DeclContext *
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -613,6 +616,20 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
return DB;
|
||||
}
|
||||
|
||||
// Adds a DeclContext to the diagnostic. The enable_if template magic is here
|
||||
// so that we only match those arguments that are (statically) DeclContexts;
|
||||
// other arguments that derive from DeclContext (e.g., RecordDecls) will not
|
||||
// match.
|
||||
template<typename T>
|
||||
inline
|
||||
typename llvm::enable_if<llvm::is_same<T, DeclContext>,
|
||||
const DiagnosticBuilder &>::type
|
||||
operator<<(const DiagnosticBuilder &DB, T *DC) {
|
||||
DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
|
||||
Diagnostic::ak_declcontext);
|
||||
return DB;
|
||||
}
|
||||
|
||||
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
const SourceRange &R) {
|
||||
DB.AddSourceRange(R);
|
||||
|
||||
@@ -1107,10 +1107,8 @@ def note_explicit_instantiation_candidate : Note<
|
||||
|
||||
// C++ typename-specifiers
|
||||
def err_typename_nested_not_found : Error<"no type named %0 in %1">;
|
||||
def err_typename_nested_not_found_global : Error<
|
||||
"no type named %0 in the global namespace">;
|
||||
def err_typename_nested_not_type : Error<
|
||||
"typename specifier refers to non-type member %0">;
|
||||
"typename specifier refers to non-type member %0 in %1">;
|
||||
def note_typename_refers_here : Note<
|
||||
"referenced member %0 is declared here">;
|
||||
|
||||
@@ -1405,17 +1403,11 @@ def warn_subscript_is_char : Warning<"array subscript is of type 'char'">,
|
||||
InGroup<CharSubscript>, DefaultIgnore;
|
||||
|
||||
def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">;
|
||||
def err_typecheck_no_member_deprecated : Error<"no member named %0">;
|
||||
def err_typecheck_record_no_member : Error<
|
||||
"no member named %0 in %select{struct|union|class|enum}1 %q2">;
|
||||
def err_typecheck_namespace_no_member : Error<
|
||||
"no member named %0 in namespace %q1">;
|
||||
def err_typecheck_global_namespace_no_member : Error<
|
||||
"no member named %0 in the global namespace">;
|
||||
def err_no_member : Error<"no member named %0 in %1">;
|
||||
|
||||
def err_member_redeclared : Error<"class member cannot be redeclared">;
|
||||
def err_member_def_does_not_match : Error<
|
||||
"out-of-line definition does not match any declaration in %0">;
|
||||
"out-of-line definition of %0 does not match any declaration in %1">;
|
||||
def err_nonstatic_member_out_of_line : Error<
|
||||
"non-static data member defined out-of-line">;
|
||||
def err_qualified_typedef_declarator : Error<
|
||||
|
||||
@@ -802,6 +802,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
|
||||
case Diagnostic::ak_declarationname:
|
||||
case Diagnostic::ak_nameddecl:
|
||||
case Diagnostic::ak_nestednamespec:
|
||||
case Diagnostic::ak_declcontext:
|
||||
getDiags()->ConvertArgToString(getArgKind(ArgNo), getRawArg(ArgNo),
|
||||
Modifier, ModifierLen,
|
||||
Argument, ArgumentLen, OutStr);
|
||||
|
||||
@@ -23,6 +23,54 @@
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
using namespace clang;
|
||||
|
||||
/// \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) {
|
||||
// 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()) {
|
||||
S = "'"+S+"' (aka '";
|
||||
S += DesugaredTy.getAsString(Context.PrintingPolicy);
|
||||
S += "')";
|
||||
return S;
|
||||
}
|
||||
|
||||
S = "'" + S + "'";
|
||||
return S;
|
||||
}
|
||||
|
||||
/// ConvertQualTypeToStringFn - This function is used to pretty print the
|
||||
/// specified QualType as a string in diagnostics.
|
||||
static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
|
||||
@@ -33,50 +81,14 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
|
||||
ASTContext &Context = *static_cast<ASTContext*>(Cookie);
|
||||
|
||||
std::string S;
|
||||
bool NeedQuotes = true;
|
||||
if (Kind == Diagnostic::ak_qualtype) {
|
||||
assert(ModLen == 0 && ArgLen == 0 &&
|
||||
"Invalid modifier for QualType argument");
|
||||
|
||||
QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));
|
||||
|
||||
// FIXME: Playing with std::string is really slow.
|
||||
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()) {
|
||||
S = "'"+S+"' (aka '";
|
||||
S += DesugaredTy.getAsString(Context.PrintingPolicy);
|
||||
S += "')";
|
||||
Output.append(S.begin(), S.end());
|
||||
return;
|
||||
}
|
||||
|
||||
S = ConvertTypeToDiagnosticString(Context, Ty);
|
||||
NeedQuotes = false;
|
||||
} else if (Kind == Diagnostic::ak_declarationname) {
|
||||
|
||||
DeclarationName N = DeclarationName::getFromOpaqueInteger(Val);
|
||||
@@ -101,16 +113,50 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
|
||||
reinterpret_cast<NamedDecl*>(Val)->getNameForDiagnostic(S,
|
||||
Context.PrintingPolicy,
|
||||
Qualified);
|
||||
} else {
|
||||
} else if (Kind == Diagnostic::ak_nestednamespec) {
|
||||
llvm::raw_string_ostream OS(S);
|
||||
assert(Kind == Diagnostic::ak_nestednamespec);
|
||||
reinterpret_cast<NestedNameSpecifier*> (Val)->print(OS,
|
||||
Context.PrintingPolicy);
|
||||
} else {
|
||||
assert(Kind == 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()) {
|
||||
// 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;
|
||||
} else {
|
||||
// FIXME: Get these strings from some localized place
|
||||
NamedDecl *ND = cast<NamedDecl>(DC);
|
||||
if (isa<NamespaceDecl>(ND))
|
||||
S += "namespace ";
|
||||
else if (isa<ObjCMethodDecl>(ND))
|
||||
S += "method ";
|
||||
else if (isa<FunctionDecl>(ND))
|
||||
S += "function ";
|
||||
|
||||
S += "'";
|
||||
ND->getNameForDiagnostic(S, Context.PrintingPolicy, true);
|
||||
S += "'";
|
||||
NeedQuotes = false;
|
||||
}
|
||||
}
|
||||
|
||||
Output.push_back('\'');
|
||||
if (NeedQuotes)
|
||||
Output.push_back('\'');
|
||||
|
||||
Output.append(S.begin(), S.end());
|
||||
Output.push_back('\'');
|
||||
|
||||
if (NeedQuotes)
|
||||
Output.push_back('\'');
|
||||
}
|
||||
|
||||
|
||||
@@ -363,31 +409,6 @@ NamedDecl *Sema::getCurFunctionOrMethodDecl() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Sema::DiagnoseMissingMember(SourceLocation MemberLoc,
|
||||
DeclarationName Member,
|
||||
NestedNameSpecifier *NNS, SourceRange Range) {
|
||||
switch (NNS->getKind()) {
|
||||
default: assert(0 && "Unexpected nested name specifier kind!");
|
||||
case NestedNameSpecifier::TypeSpec: {
|
||||
const Type *Ty = Context.getCanonicalType(NNS->getAsType());
|
||||
RecordDecl *RD = cast<RecordType>(Ty)->getDecl();
|
||||
Diag(MemberLoc, diag::err_typecheck_record_no_member)
|
||||
<< Member << RD->getTagKind() << RD << Range;
|
||||
break;
|
||||
}
|
||||
case NestedNameSpecifier::Namespace: {
|
||||
Diag(MemberLoc, diag::err_typecheck_namespace_no_member)
|
||||
<< Member << NNS->getAsNamespace() << Range;
|
||||
break;
|
||||
}
|
||||
case NestedNameSpecifier::Global: {
|
||||
Diag(MemberLoc, diag::err_typecheck_global_namespace_no_member)
|
||||
<< Member << Range;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
|
||||
if (!this->Emit())
|
||||
return;
|
||||
|
||||
@@ -3720,9 +3720,6 @@ public:
|
||||
QualType FieldTy, const Expr *BitWidth,
|
||||
bool *ZeroWidth = 0);
|
||||
|
||||
void DiagnoseMissingMember(SourceLocation MemberLoc, DeclarationName Member,
|
||||
NestedNameSpecifier *NNS, SourceRange Range);
|
||||
|
||||
/// adjustFunctionParamType - Converts the type of a function parameter to a
|
||||
// type that can be passed as an argument type to
|
||||
/// ASTContext::getFunctionType.
|
||||
|
||||
@@ -471,9 +471,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
|
||||
if (SD)
|
||||
DiagID = diag::err_expected_class_or_namespace;
|
||||
else if (SS.isSet()) {
|
||||
DiagnoseMissingMember(IdLoc, DeclarationName(&II),
|
||||
(NestedNameSpecifier *)SS.getScopeRep(),
|
||||
SS.getRange());
|
||||
Diag(IdLoc, diag::err_no_member) << &II << LookupCtx << SS.getRange();
|
||||
return 0;
|
||||
} else
|
||||
DiagID = diag::err_undeclared_var_use;
|
||||
|
||||
@@ -2229,10 +2229,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||
}
|
||||
} else if (D.getCXXScopeSpec().isSet()) {
|
||||
// No previous declaration in the qualifying scope.
|
||||
NestedNameSpecifier *NNS =
|
||||
(NestedNameSpecifier *)D.getCXXScopeSpec().getScopeRep();
|
||||
DiagnoseMissingMember(D.getIdentifierLoc(), Name, NNS,
|
||||
D.getCXXScopeSpec().getRange());
|
||||
Diag(D.getIdentifierLoc(), diag::err_no_member)
|
||||
<< Name << computeDeclContext(D.getCXXScopeSpec(), true)
|
||||
<< D.getCXXScopeSpec().getRange();
|
||||
NewVD->setInvalidDecl();
|
||||
}
|
||||
|
||||
@@ -2844,7 +2843,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||
// matches (e.g., those that differ only in cv-qualifiers and
|
||||
// whether the parameter types are references).
|
||||
Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match)
|
||||
<< cast<NamedDecl>(DC) << D.getCXXScopeSpec().getRange();
|
||||
<< Name << DC << D.getCXXScopeSpec().getRange();
|
||||
NewFD->setInvalidDecl();
|
||||
|
||||
LookupResult Prev;
|
||||
|
||||
@@ -2767,7 +2767,8 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc,
|
||||
LookupQualifiedName(R, LookupContext, Name, LookupOrdinaryName);
|
||||
|
||||
if (R.empty()) {
|
||||
DiagnoseMissingMember(IdentLoc, Name, NNS, SS.getRange());
|
||||
Diag(IdentLoc, diag::err_no_member)
|
||||
<< Name << LookupContext << SS.getRange();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -802,12 +802,11 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
|
||||
else {
|
||||
// If this name wasn't predeclared and if this is not a function call,
|
||||
// diagnose the problem.
|
||||
if (SS && !SS->isEmpty()) {
|
||||
DiagnoseMissingMember(Loc, Name,
|
||||
(NestedNameSpecifier *)SS->getScopeRep(),
|
||||
SS->getRange());
|
||||
return ExprError();
|
||||
} else if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
|
||||
if (SS && !SS->isEmpty())
|
||||
return ExprError(Diag(Loc, diag::err_no_member)
|
||||
<< Name << computeDeclContext(*SS, false)
|
||||
<< SS->getRange());
|
||||
else if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
|
||||
Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
|
||||
return ExprError(Diag(Loc, diag::err_undeclared_use)
|
||||
<< Name.getAsString());
|
||||
@@ -2185,8 +2184,8 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
||||
LookupQualifiedName(Result, DC, MemberName, LookupMemberName, false);
|
||||
|
||||
if (Result.empty())
|
||||
return ExprError(Diag(MemberLoc, diag::err_typecheck_no_member_deprecated)
|
||||
<< MemberName << BaseExpr->getSourceRange());
|
||||
return ExprError(Diag(MemberLoc, diag::err_no_member)
|
||||
<< MemberName << DC << BaseExpr->getSourceRange());
|
||||
if (Result.isAmbiguous()) {
|
||||
DiagnoseAmbiguousLookup(Result, MemberName, MemberLoc,
|
||||
BaseExpr->getSourceRange());
|
||||
@@ -5689,8 +5688,8 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
|
||||
= dyn_cast_or_null<FieldDecl>(R.getAsSingleDecl(Context));
|
||||
// FIXME: Leaks Res
|
||||
if (!MemberDecl)
|
||||
return ExprError(Diag(BuiltinLoc, diag::err_typecheck_no_member_deprecated)
|
||||
<< OC.U.IdentInfo << SourceRange(OC.LocStart, OC.LocEnd));
|
||||
return ExprError(Diag(BuiltinLoc, diag::err_no_member)
|
||||
<< OC.U.IdentInfo << RD << SourceRange(OC.LocStart, OC.LocEnd));
|
||||
|
||||
// FIXME: C++: Verify that MemberDecl isn't a static field.
|
||||
// FIXME: Verify that MemberDecl isn't a bitfield.
|
||||
|
||||
@@ -3903,10 +3903,7 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II,
|
||||
Decl *Referenced = 0;
|
||||
switch (Result.getKind()) {
|
||||
case LookupResult::NotFound:
|
||||
if (Ctx->isTranslationUnit())
|
||||
DiagID = diag::err_typename_nested_not_found_global;
|
||||
else
|
||||
DiagID = diag::err_typename_nested_not_found;
|
||||
DiagID = diag::err_typename_nested_not_found;
|
||||
break;
|
||||
|
||||
case LookupResult::Found:
|
||||
@@ -3933,10 +3930,7 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II,
|
||||
|
||||
// If we get here, it's because name lookup did not find a
|
||||
// type. Emit an appropriate diagnostic and return an error.
|
||||
if (NamedDecl *NamedCtx = dyn_cast<NamedDecl>(Ctx))
|
||||
Diag(Range.getEnd(), DiagID) << Range << Name << NamedCtx;
|
||||
else
|
||||
Diag(Range.getEnd(), DiagID) << Range << Name;
|
||||
Diag(Range.getEnd(), DiagID) << Range << Name << Ctx;
|
||||
if (Referenced)
|
||||
Diag(Referenced->getLocation(), diag::note_typename_refers_here)
|
||||
<< Name;
|
||||
|
||||
@@ -9,12 +9,12 @@ template<class T1> class A {
|
||||
template<> template<class X>
|
||||
class A<long>::B { };
|
||||
|
||||
// FIXME: If we make the explicit specialization of A<long>::B, above, into
|
||||
// a specialization of A<int>::B, our diagnostic is correct but not very
|
||||
// helpful.
|
||||
template<> template<> template<class T>
|
||||
void A<int>::B<double>::mf1(T t) { }
|
||||
|
||||
template<> template<> template<class T>
|
||||
void A<long>::B<double>::mf1(T t) { } // expected-error{{does not match}}
|
||||
|
||||
// FIXME: This diagnostic could probably be better.
|
||||
template<class Y> template<>
|
||||
void A<Y>::B<double>::mf2() { } // expected-error{{does not refer}}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace A {
|
||||
|
||||
void f() {
|
||||
A::B::i; // expected-error {{no member named 'i' in namespace 'A::B'}}
|
||||
A::B::C::i; // expected-error {{no member named 'i' in class 'A::B::C'}}
|
||||
A::B::C::i; // expected-error {{no member named 'i' in 'class A::B::C'}}
|
||||
::i; // expected-error {{no member named 'i' in the global namespace}}
|
||||
}
|
||||
|
||||
@@ -19,18 +19,18 @@ namespace B {
|
||||
|
||||
void g() {
|
||||
A::B::D::E; // expected-error {{no member named 'D' in namespace 'A::B'}}
|
||||
B::B::C::D; // expected-error {{no member named 'C' in class 'B::B'}}
|
||||
B::B::C::D; // expected-error {{no member named 'C' in 'class B::B'}}
|
||||
::C::D; // expected-error {{no member named 'C' in the global namespace}}
|
||||
}
|
||||
|
||||
int A::B::i = 10; // expected-error {{no member named 'i' in namespace 'A::B'}}
|
||||
int A::B::C::i = 10; // expected-error {{no member named 'i' in class 'A::B::C'}}
|
||||
int A::B::S::i = 10; // expected-error {{no member named 'i' in struct 'A::B::S'}}
|
||||
int A::B::U::i = 10; // expected-error {{no member named 'i' in union 'A::B::U'}}
|
||||
int A::B::C::i = 10; // expected-error {{no member named 'i' in 'class A::B::C'}}
|
||||
int A::B::S::i = 10; // expected-error {{no member named 'i' in 'struct A::B::S'}}
|
||||
int A::B::U::i = 10; // expected-error {{no member named 'i' in 'union A::B::U'}}
|
||||
|
||||
using A::B::D; // expected-error {{no member named 'D' in namespace 'A::B'}}
|
||||
|
||||
struct S : A::B::C {
|
||||
using A::B::C::f; // expected-error {{no member named 'f' in class 'A::B::C'}}
|
||||
using A::B::C::f; // expected-error {{no member named 'f' in 'class A::B::C'}}
|
||||
|
||||
};
|
||||
|
||||
@@ -35,9 +35,9 @@ class C2 {
|
||||
int x;
|
||||
};
|
||||
|
||||
void C2::m() const { } // expected-error{{out-of-line definition does not match any declaration in 'C2'}}
|
||||
void C2::m() const { } // expected-error{{out-of-line definition of 'm' does not match any declaration in 'class C2'}}
|
||||
|
||||
void C2::f(int) { } // expected-error{{out-of-line definition does not match any declaration in 'C2'}}
|
||||
void C2::f(int) { } // expected-error{{out-of-line definition of 'f' does not match any declaration in 'class C2'}}
|
||||
|
||||
void C2::m() {
|
||||
x = 0;
|
||||
@@ -125,7 +125,7 @@ class Operators {
|
||||
operator bool();
|
||||
};
|
||||
|
||||
Operators Operators::operator+(const Operators&) { // expected-error{{out-of-line definition does not match any declaration in 'Operators'}}
|
||||
Operators Operators::operator+(const Operators&) { // expected-error{{out-of-line definition of 'operator+' does not match any declaration in 'class Operators'}}
|
||||
Operators ops;
|
||||
return ops;
|
||||
}
|
||||
@@ -143,13 +143,13 @@ namespace A {
|
||||
void g(int&); // expected-note{{member declaration nearly matches}}
|
||||
}
|
||||
|
||||
void A::f() {} // expected-error{{out-of-line definition does not match any declaration in 'A'}}
|
||||
void A::f() {} // expected-error{{out-of-line definition of 'f' does not match any declaration in namespace 'A'}}
|
||||
|
||||
void A::g(const int&) { } // expected-error{{out-of-line definition does not match any declaration in 'A'}}
|
||||
void A::g(const int&) { } // expected-error{{out-of-line definition of 'g' does not match any declaration in namespace 'A'}}
|
||||
|
||||
struct Struct { };
|
||||
|
||||
void Struct::f() { } // expected-error{{out-of-line definition does not match any declaration in 'Struct'}}
|
||||
void Struct::f() { } // expected-error{{out-of-line definition of 'f' does not match any declaration in 'struct Struct'}}
|
||||
|
||||
void global_func(int);
|
||||
void global_func2(int);
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace N {
|
||||
int i;
|
||||
|
||||
typename N::A::type *ip1 = &i;
|
||||
typename N::B::type *ip2 = &i; // expected-error{{ no type named 'type' in 'B'}}
|
||||
typename N::B::type *ip2 = &i; // expected-error{{no type named 'type' in 'struct N::B'}}
|
||||
typename N::C::type *ip3 = &i; // expected-error{{typename specifier refers to non-type member 'type'}}
|
||||
|
||||
void test(double d) {
|
||||
@@ -33,7 +33,8 @@ void test(double d) {
|
||||
namespace N {
|
||||
template<typename T>
|
||||
struct X {
|
||||
typedef typename T::type type; // expected-error 2{{no type named 'type' in 'B'}} \
|
||||
typedef typename T::type type; // expected-error {{no type named 'type' in 'struct N::B'}} \
|
||||
// expected-error {{no type named 'type' in 'struct B'}} \
|
||||
// FIXME: location info for error above isn't very good \
|
||||
// expected-error 2{{typename specifier refers to non-type member 'type'}} \
|
||||
// expected-error{{type 'int' cannot be used prior to '::' because it has no members}}
|
||||
|
||||
Reference in New Issue
Block a user