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/AST/Type.cpp b/lib/AST/Type.cpp
index d8939cc..36d5015 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1112,7 +1112,8 @@
FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
unsigned numArgs, QualType canonical,
const ExtProtoInfo &epi)
- : FunctionType(FunctionProto, result, epi.Variadic, epi.TypeQuals, canonical,
+ : FunctionType(FunctionProto, result, epi.Variadic, epi.TypeQuals,
+ epi.RefQualifier, canonical,
result->isDependentType(),
result->isVariablyModifiedType(),
result->containsUnexpandedParameterPack(),
@@ -1162,6 +1163,7 @@
ID.AddPointer(ArgTys[i].getAsOpaquePtr());
ID.AddBoolean(epi.Variadic);
ID.AddInteger(epi.TypeQuals);
+ ID.AddInteger(epi.RefQualifier);
if (epi.HasExceptionSpec) {
ID.AddBoolean(epi.HasAnyExceptionSpec);
for (unsigned i = 0; i != epi.NumExceptions; ++i)
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 8a740d4..c0ce1f2 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -354,6 +354,21 @@
S += " __attribute__((regparm (" +
llvm::utostr_32(Info.getRegParm()) + ")))";
+ AppendTypeQualList(S, T->getTypeQuals());
+
+ switch (T->getRefQualifier()) {
+ case RQ_None:
+ break;
+
+ case RQ_LValue:
+ S += " &";
+ break;
+
+ case RQ_RValue:
+ S += " &&";
+ break;
+ }
+
if (T->hasExceptionSpec()) {
S += " throw(";
if (T->hasAnyExceptionSpec())
@@ -370,8 +385,6 @@
S += ")";
}
- AppendTypeQualList(S, T->getTypeQuals());
-
print(T->getResultType(), S);
}
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);
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index a722df7..b569f4b 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -2873,6 +2873,7 @@
EPI.Variadic = Record[Idx++];
EPI.TypeQuals = Record[Idx++];
+ EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]);
EPI.HasExceptionSpec = Record[Idx++];
EPI.HasAnyExceptionSpec = Record[Idx++];
EPI.NumExceptions = Record[Idx++];
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 1e296e8..e906407 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -176,6 +176,7 @@
Writer.AddTypeRef(T->getArgType(I), Record);
Record.push_back(T->isVariadic());
Record.push_back(T->getTypeQuals());
+ Record.push_back(static_cast<unsigned>(T->getRefQualifier()));
Record.push_back(T->hasExceptionSpec());
Record.push_back(T->hasAnyExceptionSpec());
Record.push_back(T->getNumExceptions());