[cfe-commits] r150244 - in /cfe/trunk: include/clang/Basic/ lib/Parse/ lib/Sema/ test/CXX/class/class.friend/ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/ test/CXX/dcl.dcl/dcl.spec/dcl.typedef/ test/CXX/dcl.decl/dcl.meaning/dcl.fct/ test/FixIt/ test/SemaCXX/
Richard Smith
richard-llvm at metafoo.co.uk
Fri Feb 10 03:05:11 PST 2012
Author: rsmith
Date: Fri Feb 10 05:05:11 2012
New Revision: 150244
URL: http://llvm.org/viewvc/llvm-project?rev=150244&view=rev
Log:
PR11684, core issue 1417:
o Correct the handling of the restrictions on usage of cv-qualified and
ref-qualified function types.
o Fix a bug where such types were rejected in template type parameter default
arguments, due to such arguments not being treated as a template type arg
context.
o Remove the ExtWarn for usage of such types as template arguments; that was
a standard defect, not a GCC extension.
o Improve the wording and unify the code for diagnosing cv-qualifiers with the
code for diagnosing ref-qualifiers.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Parse/ParseTemplate.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/CXX/class/class.friend/p1.cpp
cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp
cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp
cfe/trunk/test/FixIt/fixit.cpp
cfe/trunk/test/SemaCXX/alias-template.cpp
cfe/trunk/test/SemaCXX/destructor.cpp
cfe/trunk/test/SemaCXX/function-type-qual.cpp
cfe/trunk/test/SemaCXX/issue547.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=150244&r1=150243&r2=150244&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Feb 10 05:05:11 2012
@@ -3720,22 +3720,11 @@
def err_invalid_member_use_in_static_method : Error<
"invalid use of member %0 in static member function">;
def err_invalid_qualified_function_type : Error<
- "type qualifier is not allowed on this function">;
-def err_invalid_ref_qualifier_function_type : Error<
- "ref-qualifier '%select{&&|&}0' is only allowed on non-static member functions,"
- " member function pointers, and typedefs of function types">;
-def ext_qualified_function_type_template_arg : ExtWarn<
- "template argument of '%0' qualified function type is a GNU extension">,
- InGroup<GNU>;
-
-def err_invalid_qualified_function_pointer : Error<
- "type qualifier is not allowed on this function %select{pointer|reference}0">;
-def err_invalid_qualified_typedef_function_type_use : Error<
- "a qualified function type cannot be used to declare a "
- "%select{static member|nonmember}0 function">;
-def err_invalid_ref_qualifier_typedef_function_type_use : Error<
- "%select{static member|nonmember}0 function cannot have a ref-qualifier "
- "'%select{&&|&}1'">;
+ "%select{static |non-}0member function %select{of type %2 |}1"
+ "cannot have '%3' qualifier">;
+def err_compound_qualified_function_type : Error<
+ "%select{block pointer|pointer|reference}0 to function type %select{%2 |}1"
+ "cannot have '%3' qualifier">;
def err_ref_qualifier_overload : Error<
"cannot overload a member function %select{without a ref-qualifier|with "
Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=150244&r1=150243&r2=150244&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Fri Feb 10 05:05:11 2012
@@ -498,9 +498,10 @@
ParsedType DefaultArg;
if (Tok.is(tok::equal)) {
EqualLoc = ConsumeToken();
- DefaultArg = ParseTypeName().get();
+ DefaultArg = ParseTypeName(/*Range=*/0,
+ Declarator::TemplateTypeArgContext).get();
}
-
+
return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, Ellipsis,
EllipsisLoc, KeyLoc, ParamName, NameLoc,
Depth, Position, EqualLoc, DefaultArg);
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=150244&r1=150243&r2=150244&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Feb 10 05:05:11 2012
@@ -4341,24 +4341,6 @@
return false;
}
- // Function pointers and references cannot have qualified function type, only
- // function pointer-to-members can do that.
- QualType Pointee;
- unsigned PtrOrRef = 0;
- if (const PointerType *Ptr = T->getAs<PointerType>())
- Pointee = Ptr->getPointeeType();
- else if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
- Pointee = Ref->getPointeeType();
- PtrOrRef = 1;
- }
- if (!Pointee.isNull() && Pointee->isFunctionProtoType() &&
- Pointee->getAs<FunctionProtoType>()->getTypeQuals() != 0) {
- Diag(NewVD->getLocation(), diag::err_invalid_qualified_function_pointer)
- << PtrOrRef;
- NewVD->setInvalidDecl();
- return false;
- }
-
if (!Previous.empty()) {
MergeVarDecl(NewVD, Previous);
return true;
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=150244&r1=150243&r2=150244&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Fri Feb 10 05:05:11 2012
@@ -1789,8 +1789,8 @@
if (D.getAttributes())
distributeTypeAttrsFromDeclarator(state, T);
- // C++0x [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
- // In C++0x, a function declarator using 'auto' must have a trailing return
+ // C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
+ // In C++11, a function declarator using 'auto' must have a trailing return
// type (this is checked later) and we can skip this. In other languages
// using auto, we need to check regardless.
if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
@@ -1852,7 +1852,7 @@
if (D.isFunctionDeclarator())
Error = 10;
- // C++0x [dcl.spec.auto]p2: 'auto' is always fine if the declarator
+ // C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator
// contains a trailing return type. That is only legal at the outermost
// level. Check all declarator chunks (outermost first) anyway, to give
// better diagnostics.
@@ -1893,7 +1893,7 @@
case Declarator::ForContext:
case Declarator::BlockLiteralContext:
case Declarator::LambdaExprContext:
- // C++0x [dcl.type]p3:
+ // C++11 [dcl.type]p3:
// A type-specifier-seq shall not define a class or enumeration unless
// it appears in the type-id of an alias-declaration (7.1.3) that is not
// the declaration of a template-declaration.
@@ -1937,6 +1937,66 @@
return T;
}
+std::string getFunctionQualifiersAsString(const FunctionProtoType *FnTy) {
+ std::string Quals =
+ Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString();
+
+ switch (FnTy->getRefQualifier()) {
+ case RQ_None:
+ break;
+
+ case RQ_LValue:
+ if (!Quals.empty())
+ Quals += ' ';
+ Quals += '&';
+ break;
+
+ case RQ_RValue:
+ if (!Quals.empty())
+ Quals += ' ';
+ Quals += "&&";
+ break;
+ }
+
+ return Quals;
+}
+
+/// Check that the function type T, which has a cv-qualifier or a ref-qualifier,
+/// can be contained within the declarator chunk DeclType, and produce an
+/// appropriate diagnostic if not.
+static void checkQualifiedFunction(Sema &S, QualType T,
+ DeclaratorChunk &DeclType) {
+ // C++98 [dcl.fct]p4 / C++11 [dcl.fct]p6: a function type with a
+ // cv-qualifier or a ref-qualifier can only appear at the topmost level
+ // of a type.
+ int DiagKind = -1;
+ switch (DeclType.Kind) {
+ case DeclaratorChunk::Paren:
+ case DeclaratorChunk::MemberPointer:
+ // These cases are permitted.
+ return;
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::Function:
+ // These cases don't allow function types at all; no need to diagnose the
+ // qualifiers separately.
+ return;
+ case DeclaratorChunk::BlockPointer:
+ DiagKind = 0;
+ break;
+ case DeclaratorChunk::Pointer:
+ DiagKind = 1;
+ break;
+ case DeclaratorChunk::Reference:
+ DiagKind = 2;
+ break;
+ }
+
+ assert(DiagKind != -1);
+ S.Diag(DeclType.Loc, diag::err_compound_qualified_function_type)
+ << DiagKind << isa<FunctionType>(T.IgnoreParens()) << T
+ << getFunctionQualifiersAsString(T->castAs<FunctionProtoType>());
+}
+
static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType declSpecType,
TypeSourceInfo *TInfo) {
@@ -1968,6 +2028,11 @@
D.getContext() == Declarator::AliasDeclContext ||
D.getContext() == Declarator::AliasTemplateContext;
+ // Does T refer to a function type with a cv-qualifier or a ref-qualifier?
+ bool IsQualifiedFunction = T->isFunctionProtoType() &&
+ (T->castAs<FunctionProtoType>()->getTypeQuals() != 0 ||
+ T->castAs<FunctionProtoType>()->getRefQualifier() != RQ_None);
+
// Walk the DeclTypeInfo, building the recursive type as we go.
// DeclTypeInfos are ordered from the identifier out, which is
// opposite of what we want :).
@@ -1975,6 +2040,10 @@
unsigned chunkIndex = e - i - 1;
state.setCurrentChunkIndex(chunkIndex);
DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
+ if (IsQualifiedFunction) {
+ checkQualifiedFunction(S, T, DeclType);
+ IsQualifiedFunction = DeclType.Kind == DeclaratorChunk::Paren;
+ }
switch (DeclType.Kind) {
case DeclaratorChunk::Paren:
T = S.BuildParenType(T);
@@ -2056,6 +2125,7 @@
// does not have a K&R-style identifier list), then the arguments are part
// of the type, otherwise the argument list is ().
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
+ IsQualifiedFunction = FTI.TypeQuals || FTI.hasRefQualifier();
// Check for auto functions and trailing return type and adjust the
// return type accordingly.
@@ -2407,113 +2477,57 @@
FnTy->getNumArgs(), EPI);
}
- // C++0x [dcl.fct]p6:
- // A ref-qualifier shall only be part of the function type for a
- // non-static member function, the function type to which a pointer to
- // member refers, or the top-level function type of a function typedef
- // declaration.
- if ((FnTy->getTypeQuals() != 0 || FnTy->getRefQualifier()) &&
- !(D.getContext() == Declarator::TemplateTypeArgContext &&
- !D.isFunctionDeclarator()) && !IsTypedefName &&
- (FreeFunction ||
- D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) {
- if (D.getContext() == Declarator::TemplateTypeArgContext) {
- // Accept qualified function types as template type arguments as a GNU
- // extension. This is also the subject of C++ core issue 547.
- std::string Quals;
- if (FnTy->getTypeQuals() != 0)
- Quals = Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString();
-
- switch (FnTy->getRefQualifier()) {
- case RQ_None:
- break;
-
- case RQ_LValue:
- if (!Quals.empty())
- Quals += ' ';
- Quals += '&';
- break;
-
- case RQ_RValue:
- if (!Quals.empty())
- Quals += ' ';
- Quals += "&&";
- break;
- }
-
- S.Diag(D.getIdentifierLoc(),
- diag::ext_qualified_function_type_template_arg)
- << Quals;
- } else {
- if (FnTy->getTypeQuals() != 0) {
- if (D.isFunctionDeclarator()) {
- SourceRange Range = D.getIdentifierLoc();
- for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) {
- const DeclaratorChunk &Chunk = D.getTypeObject(N-I-1);
- if (Chunk.Kind == DeclaratorChunk::Function &&
- Chunk.Fun.TypeQuals != 0) {
- switch (Chunk.Fun.TypeQuals) {
- case Qualifiers::Const:
- Range = Chunk.Fun.getConstQualifierLoc();
- break;
- case Qualifiers::Volatile:
- Range = Chunk.Fun.getVolatileQualifierLoc();
- break;
- case Qualifiers::Const | Qualifiers::Volatile: {
- SourceLocation CLoc = Chunk.Fun.getConstQualifierLoc();
- SourceLocation VLoc = Chunk.Fun.getVolatileQualifierLoc();
- if (S.getSourceManager()
- .isBeforeInTranslationUnit(CLoc, VLoc)) {
- Range = SourceRange(CLoc, VLoc);
- } else {
- Range = SourceRange(VLoc, CLoc);
- }
- }
- break;
- }
- break;
- }
- }
- S.Diag(Range.getBegin(), diag::err_invalid_qualified_function_type)
- << FixItHint::CreateRemoval(Range);
- } else
- S.Diag(D.getIdentifierLoc(),
- diag::err_invalid_qualified_typedef_function_type_use)
- << FreeFunction;
- }
-
- if (FnTy->getRefQualifier()) {
- if (D.isFunctionDeclarator()) {
- SourceLocation Loc = D.getIdentifierLoc();
- for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) {
- const DeclaratorChunk &Chunk = D.getTypeObject(N-I-1);
- if (Chunk.Kind == DeclaratorChunk::Function &&
- Chunk.Fun.hasRefQualifier()) {
- Loc = Chunk.Fun.getRefQualifierLoc();
- break;
- }
- }
-
- S.Diag(Loc, diag::err_invalid_ref_qualifier_function_type)
- << (FnTy->getRefQualifier() == RQ_LValue)
- << FixItHint::CreateRemoval(Loc);
- } else {
- S.Diag(D.getIdentifierLoc(),
- diag::err_invalid_ref_qualifier_typedef_function_type_use)
- << FreeFunction
- << (FnTy->getRefQualifier() == RQ_LValue);
- }
+ // C++11 [dcl.fct]p6 (w/DR1417):
+ // An attempt to specify a function type with a cv-qualifier-seq or a
+ // ref-qualifier (including by typedef-name) is ill-formed unless it is:
+ // - the function type for a non-static member function,
+ // - the function type to which a pointer to member refers,
+ // - the top-level function type of a function typedef declaration or
+ // alias-declaration,
+ // - the type-id in the default argument of a type-parameter, or
+ // - the type-id of a template-argument for a type-parameter
+ if (IsQualifiedFunction &&
+ !(!FreeFunction &&
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) &&
+ !IsTypedefName &&
+ D.getContext() != Declarator::TemplateTypeArgContext) {
+ SourceLocation Loc = D.getSourceRange().getBegin();
+ SourceRange RemovalRange;
+ unsigned I;
+ if (D.isFunctionDeclarator(I)) {
+ SmallVector<SourceLocation, 4> RemovalLocs;
+ const DeclaratorChunk &Chunk = D.getTypeObject(I);
+ assert(Chunk.Kind == DeclaratorChunk::Function);
+ if (Chunk.Fun.hasRefQualifier())
+ RemovalLocs.push_back(Chunk.Fun.getRefQualifierLoc());
+ if (Chunk.Fun.TypeQuals & Qualifiers::Const)
+ RemovalLocs.push_back(Chunk.Fun.getConstQualifierLoc());
+ if (Chunk.Fun.TypeQuals & Qualifiers::Volatile)
+ RemovalLocs.push_back(Chunk.Fun.getVolatileQualifierLoc());
+ // FIXME: We do not track the location of the __restrict qualifier.
+ //if (Chunk.Fun.TypeQuals & Qualifiers::Restrict)
+ // RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc());
+ if (!RemovalLocs.empty()) {
+ std::sort(RemovalLocs.begin(), RemovalLocs.end(),
+ SourceManager::LocBeforeThanCompare(S.getSourceManager()));
+ RemovalRange = SourceRange(RemovalLocs.front(), RemovalLocs.back());
+ Loc = RemovalLocs.front();
}
-
- // Strip the cv-qualifiers and ref-qualifiers from the type.
- FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
- EPI.TypeQuals = 0;
- EPI.RefQualifier = RQ_None;
-
- T = Context.getFunctionType(FnTy->getResultType(),
- FnTy->arg_type_begin(),
- FnTy->getNumArgs(), EPI);
}
+
+ S.Diag(Loc, diag::err_invalid_qualified_function_type)
+ << FreeFunction << D.isFunctionDeclarator() << T
+ << getFunctionQualifiersAsString(FnTy)
+ << FixItHint::CreateRemoval(RemovalRange);
+
+ // Strip the cv-qualifiers and ref-qualifiers from the type.
+ FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
+ EPI.TypeQuals = 0;
+ EPI.RefQualifier = RQ_None;
+
+ T = Context.getFunctionType(FnTy->getResultType(),
+ FnTy->arg_type_begin(),
+ FnTy->getNumArgs(), EPI);
}
}
Modified: cfe/trunk/test/CXX/class/class.friend/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.friend/p1.cpp?rev=150244&r1=150243&r2=150244&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class/class.friend/p1.cpp (original)
+++ cfe/trunk/test/CXX/class/class.friend/p1.cpp Fri Feb 10 05:05:11 2012
@@ -58,7 +58,7 @@
friend A operator|(const A& r); // expected-error {{overloaded 'operator|' must be a binary operator (has 1 parameter)}}
friend operator bool() const; // expected-error {{must use a qualified name when declaring a conversion operator as a friend}} \
- // expected-error{{type qualifier is not allowed on this function}}
+ // expected-error{{non-member function cannot have 'const' qualifier}}
typedef void ftypedef();
friend ftypedef typedeffed_function; // okay (because it's not declared as a member)
Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp?rev=150244&r1=150243&r2=150244&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp Fri Feb 10 05:05:11 2012
@@ -60,7 +60,7 @@
template <const auto (*a)[3] = &ints> class D { }; // expected-error{{'auto' not allowed in template parameter}}
enum E : auto {}; // expected-error{{'auto' not allowed here}}
struct F : auto {}; // expected-error{{expected class name}}
-template<typename T = auto> struct G { }; // expected-error{{'auto' not allowed here}}
+template<typename T = auto> struct G { }; // expected-error{{'auto' not allowed in template argument}}
using A = auto; // expected-error{{'auto' not allowed in type alias}}
Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp?rev=150244&r1=150243&r2=150244&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp Fri Feb 10 05:05:11 2012
@@ -15,8 +15,7 @@
using C = virtual void(int n); // expected-error {{type name does not allow function specifier}}
using D = explicit void(int n); // expected-error {{type name does not allow function specifier}}
using E = void(int n) throw(); // expected-error {{exception specifications are not allowed in type aliases}}
- // FIXME: this is illegal; we incorrectly accept it for typedefs too.
- using F = void(*)(int n) &&; // expected-err
+ using F = void(*)(int n) &&; // expected-error {{pointer to function type cannot have '&&' qualifier}}
using G = __thread void(int n); // expected-error {{type name does not allow storage class to be specified}}
using H = void(int n); // ok
Modified: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp?rev=150244&r1=150243&r2=150244&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp (original)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp Fri Feb 10 05:05:11 2012
@@ -1,20 +1,45 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
-void f0() &; // expected-error{{ref-qualifier '&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}}
-void f1() &&; // expected-error{{ref-qualifier '&&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}}
+void f0() &; // expected-error {{non-member function cannot have '&' qualifier}}
+void f1() &&; // expected-error {{non-member function cannot have '&&' qualifier}}
+void f2() const volatile &&; // expected-error {{non-member function cannot have 'const volatile &&' qualifier}}
struct X {
- void f0() &;
+ void f0() &;
void f1() &&;
- static void f2() &; // expected-error{{ref-qualifier '&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}}
- static void f3() &&; // expected-error{{ref-qualifier '&&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}}
+ static void f2() &; // expected-error{{static member function cannot have '&' qualifier}}
+ static void f3() &&; // expected-error{{static member function cannot have '&&' qualifier}}
};
typedef void func_type_lvalue() &;
typedef void func_type_rvalue() &&;
-func_type_lvalue f2; // expected-error{{nonmember function cannot have a ref-qualifier '&'}}
-func_type_rvalue f3; // expected-error{{nonmember function cannot have a ref-qualifier '&&'}}
+typedef func_type_lvalue *func_type_lvalue_ptr; // expected-error{{pointer to function type 'func_type_lvalue' (aka 'void () &') cannot have '&' qualifier}}
+typedef func_type_rvalue *func_type_rvalue_ptr; // expected-error{{pointer to function type 'func_type_rvalue' (aka 'void () &&') cannot have '&&' qualifier}}
+
+typedef func_type_lvalue &func_type_lvalue_ref; // expected-error{{reference to function type 'func_type_lvalue' (aka 'void () &') cannot have '&' qualifier}}
+typedef func_type_rvalue &func_type_rvalue_ref; // expected-error{{reference to function type 'func_type_rvalue' (aka 'void () &&') cannot have '&&' qualifier}}
+
+template<typename T = func_type_lvalue> struct wrap {
+ typedef T val;
+ typedef T *ptr;
+ typedef T &ref;
+};
+
+using func_type_lvalue = wrap<>::val;
+using func_type_lvalue = wrap<func_type_lvalue>::val;
+using func_type_rvalue = wrap<func_type_rvalue>::val;
+
+using func_type_lvalue_ptr = wrap<>::ptr;
+using func_type_lvalue_ptr = wrap<func_type_lvalue>::ptr;
+using func_type_rvalue_ptr = wrap<func_type_rvalue>::ptr;
+
+using func_type_lvalue_ref = wrap<>::ref;
+using func_type_lvalue_ref = wrap<func_type_lvalue>::ref;
+using func_type_rvalue_ref = wrap<func_type_rvalue>::ref;
+
+func_type_lvalue f2; // expected-error{{non-member function of type 'func_type_lvalue' (aka 'void () &') cannot have '&' qualifier}}
+func_type_rvalue f3; // expected-error{{non-member function of type 'func_type_rvalue' (aka 'void () &&') cannot have '&&' qualifier}}
struct Y {
func_type_lvalue f0;
@@ -25,4 +50,4 @@
void (X::*mpf2)() && = &X::f1;
-void (f() &&); // expected-error{{ref-qualifier '&&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}}
+void (f() &&); // expected-error{{non-member function cannot have '&&' qualifier}}
Modified: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp?rev=150244&r1=150243&r2=150244&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp (original)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp Fri Feb 10 05:05:11 2012
@@ -1,14 +1,20 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-void f() const; // expected-error{{type qualifier is not allowed on this function}}
+typedef void F() const;
+
+void f() const; // expected-error {{non-member function cannot have 'const' qualifier}}
+F g; // expected-error {{non-member function of type 'F' (aka 'void () const') cannot have 'const' qualifier}}
struct X {
void f() const;
- friend void g() const; // expected-error{{type qualifier is not allowed on this function}}
- static void h() const; // expected-error{{type qualifier is not allowed on this function}}
+ friend void g() const; // expected-error {{non-member function cannot have 'const' qualifier}}
+ static void h() const; // expected-error {{static member function cannot have 'const' qualifier}}
+ F i; // ok
+ friend F j; // expected-error {{non-member function of type 'F' (aka 'void () const') cannot have 'const' qualifier}}
+ static F k; // expected-error {{static member function of type 'F' (aka 'void () const') cannot have 'const' qualifier}}
};
struct Y {
friend void X::f() const;
- friend void ::f() const; // expected-error{{type qualifier is not allowed on this function}}
+ friend void ::f() const; // expected-error {{non-member function cannot have 'const' qualifier}}
};
Modified: cfe/trunk/test/FixIt/fixit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit.cpp?rev=150244&r1=150243&r2=150244&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/fixit.cpp (original)
+++ cfe/trunk/test/FixIt/fixit.cpp Fri Feb 10 05:05:11 2012
@@ -162,9 +162,9 @@
aPtr = br; // expected-error {{assigning to 'AD *' from incompatible type 'BD'; take the address with &}}
}
-void foo1() const {} // expected-error {{type qualifier is not allowed on this function}}
-void foo2() volatile {} // expected-error {{type qualifier is not allowed on this function}}
-void foo3() const volatile {} // expected-error {{type qualifier is not allowed on this function}}
+void foo1() const {} // expected-error {{non-member function cannot have 'const' qualifier}}
+void foo2() volatile {} // expected-error {{non-member function cannot have 'volatile' qualifier}}
+void foo3() const volatile {} // expected-error {{non-member function cannot have 'const volatile' qualifier}}
struct S { void f(int, char); };
int itsAComma,
Modified: cfe/trunk/test/SemaCXX/alias-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/alias-template.cpp?rev=150244&r1=150243&r2=150244&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/alias-template.cpp (original)
+++ cfe/trunk/test/SemaCXX/alias-template.cpp Fri Feb 10 05:05:11 2012
@@ -12,8 +12,7 @@
template<typename U> using C = virtual void(int n); // expected-error {{type name does not allow function specifier}}
template<typename U> using D = explicit void(int n); // expected-error {{type name does not allow function specifier}}
template<typename U> using E = void(int n) throw(); // expected-error {{exception specifications are not allowed in type aliases}}
- // FIXME: this is illegal; we incorrectly accept it for typedefs too.
- template<typename U> using F = void(*)(int n) &&; // expected-err
+ template<typename U> using F = void(*)(int n) &&; // expected-error {{pointer to function type cannot have '&&' qualifier}}
template<typename U> using G = __thread void(int n); // expected-error {{type name does not allow storage class to be specified}}
template<typename U> using H = void(int n); // ok
Modified: cfe/trunk/test/SemaCXX/destructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/destructor.cpp?rev=150244&r1=150243&r2=150244&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/destructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/destructor.cpp Fri Feb 10 05:05:11 2012
@@ -16,7 +16,7 @@
struct D {
static void ~D(int, ...) const { } // \
- // expected-error{{type qualifier is not allowed on this function}} \
+ // expected-error{{static member function cannot have 'const' qualifier}} \
// expected-error{{destructor cannot be declared 'static'}} \
// expected-error{{destructor cannot have any parameters}} \
// expected-error{{destructor cannot be variadic}} \
Modified: cfe/trunk/test/SemaCXX/function-type-qual.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/function-type-qual.cpp?rev=150244&r1=150243&r2=150244&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/function-type-qual.cpp (original)
+++ cfe/trunk/test/SemaCXX/function-type-qual.cpp Fri Feb 10 05:05:11 2012
@@ -1,17 +1,17 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-void f() const; // expected-error {{type qualifier is not allowed on this function}}
-void (*pf)() const; // expected-error {{type qualifier is not allowed on this function pointer}}
-void (&rf)() const = f; // expected-error {{type qualifier is not allowed on this function reference}}
+void f() const; // expected-error {{non-member function cannot have 'const' qualifier}}
+void (*pf)() const; // expected-error {{pointer to function type cannot have 'const' qualifier}}
+extern void (&rf)() const; // expected-error {{reference to function type cannot have 'const' qualifier}}
-typedef void cfn() const;
-cfn f2; // expected-error {{a qualified function type cannot be used to declare a nonmember function}}
+typedef void cfn() const;
+cfn f2; // expected-error {{non-member function of type 'cfn' (aka 'void () const') cannot have 'const' qualifier}}
class C {
void f() const;
cfn f2;
- static void f3() const; // expected-error {{type qualifier is not allowed on this function}}
- static cfn f4; // expected-error {{a qualified function type cannot be used to declare a static member function}}
+ static void f3() const; // expected-error {{static member function cannot have 'const' qualifier}}
+ static cfn f4; // expected-error {{static member function of type 'cfn' (aka 'void () const') cannot have 'const' qualifier}}
void m1() {
x = 0;
Modified: cfe/trunk/test/SemaCXX/issue547.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/issue547.cpp?rev=150244&r1=150243&r2=150244&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/issue547.cpp (original)
+++ cfe/trunk/test/SemaCXX/issue547.cpp Fri Feb 10 05:05:11 2012
@@ -11,17 +11,17 @@
};
template<typename R, typename ...Args>
-struct classify_function<R(Args...) const> { // expected-warning{{template argument of 'const' qualified function type is a GNU extension}}
+struct classify_function<R(Args...) const> {
static const unsigned value = 2;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args...) volatile> { // expected-warning{{template argument of 'volatile' qualified function type is a GNU extension}}
+struct classify_function<R(Args...) volatile> {
static const unsigned value = 3;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args...) const volatile> { // expected-warning{{template argument of 'const volatile' qualified function type is a GNU extension}}
+struct classify_function<R(Args...) const volatile> {
static const unsigned value = 4;
};
@@ -31,27 +31,27 @@
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) const> { // expected-warning{{template argument of 'const' qualified function type is a GNU extension}}
+struct classify_function<R(Args......) const> {
static const unsigned value = 6;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) volatile> { // expected-warning{{template argument of 'volatile' qualified function type is a GNU extension}}
+struct classify_function<R(Args......) volatile> {
static const unsigned value = 7;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) const volatile> { // expected-warning{{template argument of 'const volatile' qualified function type is a GNU extension}}
+struct classify_function<R(Args......) const volatile> {
static const unsigned value = 8;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) &&> { // expected-warning{{template argument of '&&' qualified function type is a GNU extension}}
+struct classify_function<R(Args......) &&> {
static const unsigned value = 9;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) const &> { // expected-warning{{template argument of 'const &' qualified function type is a GNU extension}}
+struct classify_function<R(Args......) const &> {
static const unsigned value = 10;
};
More information about the cfe-commits
mailing list