Rvalue references for *this:
- Add ref-qualifiers to the type system; they are part of the
canonical type. Print & profile ref-qualifiers
- Translate the ref-qualifier from the Declarator chunk for
functions to the function type.
- Diagnose mis-uses of ref-qualifiers w.r.t. static member
functions, free functions, constructors, destructors, etc.
- Add serialization and deserialization of ref-qualifiers.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124281 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index d5dea78..78d9a5b 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3023,6 +3023,15 @@
D.setInvalidType();
}
+ // C++0x [class.ctor]p4:
+ // A constructor shall not be declared with a ref-qualifier.
+ if (FTI.hasRefQualifier()) {
+ Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor)
+ << FTI.RefQualifierIsLValueRef
+ << FixItHint::CreateRemoval(FTI.getRefQualifierLoc());
+ D.setInvalidType();
+ }
+
// Rebuild the function type "R" without any type qualifiers (in
// case any of the errors above fired) and with "void" as the
// return type, since constructors don't have return types.
@@ -3032,7 +3041,8 @@
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
EPI.TypeQuals = 0;
-
+ EPI.RefQualifier = RQ_None;
+
return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(),
Proto->getNumArgs(), EPI);
}
@@ -3173,6 +3183,15 @@
D.setInvalidType();
}
+ // C++0x [class.dtor]p2:
+ // A destructor shall not be declared with a ref-qualifier.
+ if (FTI.hasRefQualifier()) {
+ Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_destructor)
+ << FTI.RefQualifierIsLValueRef
+ << FixItHint::CreateRemoval(FTI.getRefQualifierLoc());
+ D.setInvalidType();
+ }
+
// Make sure we don't have any parameters.
if (FTI.NumArgs > 0 && !FTIHasSingleVoidArgument(FTI)) {
Diag(D.getIdentifierLoc(), diag::err_destructor_with_params);
@@ -3199,6 +3218,7 @@
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
EPI.Variadic = false;
EPI.TypeQuals = 0;
+ EPI.RefQualifier = RQ_None;
return Context.getFunctionType(Context.VoidTy, 0, 0, EPI);
}
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 00d92bc..70e9973 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2106,6 +2106,7 @@
ParamTypes.data(), ParamTypes.size(),
Proto->isVariadic(),
Proto->getTypeQuals(),
+ Proto->getRefQualifier(),
Function->getLocation(),
Function->getDeclName(),
Proto->getExtInfo());
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index b663f58..64d5c42 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1269,6 +1269,7 @@
QualType *ParamTypes,
unsigned NumParamTypes,
bool Variadic, unsigned Quals,
+ RefQualifierKind RefQualifier,
SourceLocation Loc, DeclarationName Entity,
FunctionType::ExtInfo Info) {
if (T->isArrayType() || T->isFunctionType()) {
@@ -1294,6 +1295,7 @@
FunctionProtoType::ExtProtoInfo EPI;
EPI.Variadic = Variadic;
EPI.TypeQuals = Quals;
+ EPI.RefQualifier = RefQualifier;
EPI.ExtInfo = Info;
return Context.getFunctionType(T, ParamTypes, NumParamTypes, EPI);
@@ -1722,7 +1724,10 @@
FunctionProtoType::ExtProtoInfo EPI;
EPI.Variadic = FTI.isVariadic;
EPI.TypeQuals = FTI.TypeQuals;
-
+ EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None
+ : FTI.RefQualifierIsLValueRef? RQ_LValue
+ : RQ_RValue;
+
// Otherwise, we have a function with an argument list that is
// potentially variadic.
llvm::SmallVector<QualType, 16> ArgTys;
@@ -1876,21 +1881,44 @@
FreeFunction = (DC && !DC->isRecord());
}
- if (FnTy->getTypeQuals() != 0 &&
+ // 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.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
(FreeFunction ||
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) {
- if (D.isFunctionDeclarator())
- Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_function_type);
- else
- Diag(D.getIdentifierLoc(),
- diag::err_invalid_qualified_typedef_function_type_use)
- << FreeFunction;
-
- // Strip the cv-quals from the type.
+ if (FnTy->getTypeQuals() != 0) {
+ if (D.isFunctionDeclarator())
+ Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_function_type);
+ else
+ Diag(D.getIdentifierLoc(),
+ diag::err_invalid_qualified_typedef_function_type_use)
+ << FreeFunction;
+ }
+
+ if (FnTy->getRefQualifier()) {
+ if (D.isFunctionDeclarator()) {
+ SourceLocation Loc
+ = D.getTypeObject(D.getNumTypeObjects()-1).Fun.getRefQualifierLoc();
+ Diag(Loc, diag::err_invalid_ref_qualifier_function_type)
+ << (FnTy->getRefQualifier() == RQ_LValue)
+ << FixItHint::CreateRemoval(Loc);
+ } else {
+ Diag(D.getIdentifierLoc(),
+ diag::err_invalid_ref_qualifier_typedef_function_type_use)
+ << FreeFunction
+ << (FnTy->getRefQualifier() == RQ_LValue);
+ }
+ }
+
+ // Strip the cv-quals and ref-qualifier 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);
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 04c45b8..3f8d3e5 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -633,6 +633,7 @@
QualType *ParamTypes,
unsigned NumParamTypes,
bool Variadic, unsigned Quals,
+ RefQualifierKind RefQualifier,
const FunctionType::ExtInfo &Info);
/// \brief Build a new unprototyped function type.
@@ -3796,6 +3797,7 @@
ParamTypes.size(),
T->isVariadic(),
T->getTypeQuals(),
+ T->getRefQualifier(),
T->getExtInfo());
if (Result.isNull())
return QualType();
@@ -7178,7 +7180,7 @@
ParamTypes.data(),
ParamTypes.size(),
BD->isVariadic(),
- 0,
+ 0, RQ_None,
BExprFunctionType->getExtInfo());
CurBlock->FunctionType = FunctionType;
@@ -7373,9 +7375,10 @@
unsigned NumParamTypes,
bool Variadic,
unsigned Quals,
+ RefQualifierKind RefQualifier,
const FunctionType::ExtInfo &Info) {
return SemaRef.BuildFunctionType(T, ParamTypes, NumParamTypes, Variadic,
- Quals,
+ Quals, RefQualifier,
getDerived().getBaseLocation(),
getDerived().getBaseEntity(),
Info);