[cfe-commits] r130974 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticCommonKinds.td include/clang/Basic/DiagnosticParseKinds.td include/clang/Sema/Sema.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp
Sean Hunt
scshunt at csclub.uwaterloo.ca
Thu May 5 18:42:00 PDT 2011
Author: coppro
Date: Thu May 5 20:42:00 2011
New Revision: 130974
URL: http://llvm.org/viewvc/llvm-project?rev=130974&view=rev
Log:
Do defaulted constructors properly.
Explictly defaultedness is correctly reflected on the AST, but there are
no changes to how that affects the definition of functions or much else
really.
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu May 5 20:42:00 2011
@@ -1365,6 +1365,8 @@
bool HasWrittenPrototype : 1;
bool IsDeleted : 1;
bool IsTrivial : 1; // sunk from CXXMethodDecl
+ bool IsDefaulted : 1; // sunk from CXXMethoDecl
+ bool IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
bool HasImplicitReturnZero : 1;
bool IsLateTemplateParsed : 1;
@@ -1566,6 +1568,16 @@
bool isTrivial() const { return IsTrivial; }
void setTrivial(bool IT) { IsTrivial = IT; }
+ /// Whether this function is defaulted per C++0x. Only valid for
+ /// special member functions.
+ bool isDefaulted() const { return IsDefaulted; }
+ void setDefaulted(bool D = true) { IsDefaulted = D; }
+
+ /// Whether this function is explicitly defaulted per C++0x. Only valid
+ /// for special member functions.
+ bool isExplicitlyDefaulted() const { return IsExplicitlyDefaulted; }
+ void setExplicitlyDefaulted(bool ED = true) { IsExplicitlyDefaulted = ED; }
+
/// Whether falling off this function implicitly returns null/zero.
/// If a more specific implicit return value is required, front-ends
/// should synthesize the appropriate return statements.
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu May 5 20:42:00 2011
@@ -1189,6 +1189,12 @@
CXXMethodDecl *getCanonicalDecl() {
return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
}
+
+ /// isUserProvided - True if it is either an implicit constructor or
+ /// if it was defaulted or deleted on first declaration.
+ bool isUserProvided() const {
+ return getCanonicalDecl()->isDeleted() || getCanonicalDecl()->isDefaulted();
+ }
///
void addOverriddenMethod(const CXXMethodDecl *MD);
Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td Thu May 5 20:42:00 2011
@@ -52,6 +52,10 @@
def err_expected_namespace_name : Error<"expected namespace name">;
def ext_variadic_templates : ExtWarn<
"variadic templates are a C++0x extension">, InGroup<CXX0x>;
+def err_default_special_members : Error<
+ "Only special member functions may be defaulted">;
+def err_friends_define_only_namespace_scope : Error<
+ "Cannot define a function with non-namespace scope in a friend declaration">;
// Sema && Lex
def ext_longlong : Extension<
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu May 5 20:42:00 2011
@@ -434,6 +434,9 @@
def warn_deleted_function_accepted_as_extension: ExtWarn<
"deleted function definition accepted as a C++0x extension">, InGroup<CXX0x>;
+def warn_defaulted_function_accepted_as_extension: ExtWarn<
+ "defaulted function definition accepted as a C++0x extension">,
+ InGroup<CXX0x>;
// C++0x alias-declaration
def ext_alias_declaration : ExtWarn<
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu May 5 20:42:00 2011
@@ -935,7 +935,8 @@
Decl *HandleDeclarator(Scope *S, Declarator &D,
MultiTemplateParamsArg TemplateParameterLists,
- bool IsFunctionDefinition);
+ bool IsFunctionDefinition,
+ SourceLocation DefLoc = SourceLocation());
void RegisterLocallyScopedExternCDecl(NamedDecl *ND,
const LookupResult &Previous,
Scope *S);
@@ -963,7 +964,8 @@
LookupResult &Previous,
MultiTemplateParamsArg TemplateParamLists,
bool IsFunctionDefinition,
- bool &Redeclaration);
+ bool &Redeclaration,
+ SourceLocation DefLoc = SourceLocation());
bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
void DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
void CheckFunctionDeclaration(Scope *S,
@@ -3063,7 +3065,8 @@
MultiTemplateParamsArg TemplateParameterLists,
Expr *BitfieldWidth, const VirtSpecifiers &VS,
Expr *Init, bool IsDefinition,
- bool Deleted = false);
+ bool Deleted = false,
+ SourceLocation DefLoc = SourceLocation());
MemInitResult ActOnMemInitializer(Decl *ConstructorD,
Scope *S,
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu May 5 20:42:00 2011
@@ -966,6 +966,10 @@
Diag(DelLoc, diag::warn_deleted_function_accepted_as_extension);
Actions.SetDeclDeleted(ThisDecl, DelLoc);
+ } else if (Tok.is(tok::kw_default)) {
+ SourceLocation DefLoc = ConsumeToken();
+
+ Diag(DefLoc, diag::err_default_special_members);
} else {
if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
EnterScope(0);
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu May 5 20:42:00 2011
@@ -1648,6 +1648,7 @@
ExprResult BitfieldSize;
ExprResult Init;
bool Deleted = false;
+ SourceLocation DefLoc;
while (1) {
// member-declarator:
@@ -1679,6 +1680,10 @@
Diag(Tok, diag::warn_deleted_function_accepted_as_extension);
ConsumeToken();
Deleted = true;
+ } else if (Tok.is(tok::kw_default)) {
+ if (!getLang().CPlusPlus0x)
+ Diag(Tok, diag::warn_defaulted_function_accepted_as_extension);
+ DefLoc = ConsumeToken();
} else {
Init = ParseInitializer();
if (Init.isInvalid())
@@ -1706,6 +1711,9 @@
Decl *ThisDecl = 0;
if (DS.isFriendSpecified()) {
+ if (DefLoc.isValid())
+ Diag(DefLoc, diag::err_default_special_members);
+
// TODO: handle initializers, bitfields, 'delete'
ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo,
/*IsDefinition*/ false,
@@ -1717,7 +1725,7 @@
BitfieldSize.release(),
VS, Init.release(),
/*IsDefinition*/Deleted,
- Deleted);
+ Deleted, DefLoc);
}
if (ThisDecl)
DeclsInGroup.push_back(ThisDecl);
@@ -1744,6 +1752,7 @@
BitfieldSize = 0;
Init = 0;
Deleted = false;
+ DefLoc = SourceLocation();
// Attributes are only allowed on the second declarator.
MaybeParseGNUAttributes(DeclaratorInfo);
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu May 5 20:42:00 2011
@@ -2919,7 +2919,8 @@
Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
MultiTemplateParamsArg TemplateParamLists,
- bool IsFunctionDefinition) {
+ bool IsFunctionDefinition,
+ SourceLocation DefLoc) {
// TODO: consider using NameInfo for diagnostic.
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
DeclarationName Name = NameInfo.getName();
@@ -2962,7 +2963,6 @@
<< D.getCXXScopeSpec().getRange();
return 0;
}
-
bool IsDependentContext = DC->isDependentContext();
if (!IsDependentContext &&
@@ -3121,6 +3121,9 @@
bool Redeclaration = false;
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
+ if (DefLoc.isValid())
+ Diag(DefLoc, diag::err_default_special_members);
+
if (TemplateParamLists.size()) {
Diag(D.getIdentifierLoc(), diag::err_template_typedef);
return 0;
@@ -3130,8 +3133,9 @@
} else if (R->isFunctionType()) {
New = ActOnFunctionDeclarator(S, D, DC, R, TInfo, Previous,
move(TemplateParamLists),
- IsFunctionDefinition, Redeclaration);
+ IsFunctionDefinition, Redeclaration, DefLoc);
} else {
+ assert(!DefLoc.isValid() && "We should have caught this in a caller");
New = ActOnVariableDeclarator(S, D, DC, R, TInfo, Previous,
move(TemplateParamLists),
Redeclaration);
@@ -4003,7 +4007,8 @@
QualType R, TypeSourceInfo *TInfo,
LookupResult &Previous,
MultiTemplateParamsArg TemplateParamLists,
- bool IsFunctionDefinition, bool &Redeclaration) {
+ bool IsFunctionDefinition, bool &Redeclaration,
+ SourceLocation DefLoc) {
assert(R.getTypePtr()->isFunctionType());
// TODO: consider using NameInfo for diagnostic.
@@ -4060,6 +4065,8 @@
bool isFunctionTemplateSpecialization = false;
if (!getLangOptions().CPlusPlus) {
+ assert(!DefLoc.isValid() && "Defaulted functions are a C++ feature");
+
// Determine whether the function was written with a
// prototype. This true when:
// - there is a prototype in the declarator, or
@@ -4104,12 +4111,25 @@
R = CheckConstructorDeclarator(D, R, SC);
// Create the new declaration
- NewFD = CXXConstructorDecl::Create(Context,
+ CXXConstructorDecl *NewCD = CXXConstructorDecl::Create(
+ Context,
cast<CXXRecordDecl>(DC),
D.getSourceRange().getBegin(),
NameInfo, R, TInfo,
isExplicit, isInline,
/*isImplicitlyDeclared=*/false);
+
+ NewFD = NewCD;
+
+ if (DefLoc.isValid()) {
+ if (NewCD->isDefaultConstructor() ||
+ NewCD->isCopyOrMoveConstructor()) {
+ NewFD->setDefaulted();
+ NewFD->setExplicitlyDefaulted();
+ } else {
+ Diag(DefLoc, diag::err_default_special_members);
+ }
+ }
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
// This is a C++ destructor declaration.
if (DC->isRecord()) {
@@ -4122,6 +4142,11 @@
isInline,
/*isImplicitlyDeclared=*/false);
isVirtualOkay = true;
+
+ if (DefLoc.isValid()) {
+ NewFD->setDefaulted();
+ NewFD->setExplicitlyDefaulted();
+ }
} else {
Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
@@ -4140,6 +4165,9 @@
return 0;
}
+ if (DefLoc.isValid())
+ Diag(DefLoc, diag::err_default_special_members);
+
CheckConversionDeclarator(D, R, SC);
NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
D.getSourceRange().getBegin(),
@@ -4178,14 +4206,29 @@
isStatic = true;
// This is a C++ method declaration.
- NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
- D.getSourceRange().getBegin(),
- NameInfo, R, TInfo,
- isStatic, SCAsWritten, isInline,
- SourceLocation());
+ CXXMethodDecl *NewMD = CXXMethodDecl::Create(
+ Context, cast<CXXRecordDecl>(DC),
+ D.getSourceRange().getBegin(),
+ NameInfo, R, TInfo,
+ isStatic, SCAsWritten, isInline,
+ SourceLocation());
+ NewFD = NewMD;
isVirtualOkay = !isStatic;
+
+ if (DefLoc.isValid()) {
+ if (NewMD->isCopyAssignmentOperator() /* ||
+ NewMD->isMoveAssignmentOperator() */) {
+ NewFD->setDefaulted();
+ NewFD->setExplicitlyDefaulted();
+ } else {
+ Diag(DefLoc, diag::err_default_special_members);
+ }
+ }
} else {
+ if (DefLoc.isValid())
+ Diag(DefLoc, diag::err_default_special_members);
+
// Determine whether the function was written with a
// prototype. This true when:
// - we're in C++ (where every function has a prototype),
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=130974&r1=130973&r2=130974&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu May 5 20:42:00 2011
@@ -963,7 +963,7 @@
MultiTemplateParamsArg TemplateParameterLists,
ExprTy *BW, const VirtSpecifiers &VS,
ExprTy *InitExpr, bool IsDefinition,
- bool Deleted) {
+ bool Deleted, SourceLocation DefLoc) {
const DeclSpec &DS = D.getDeclSpec();
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
DeclarationName Name = NameInfo.getName();
@@ -1028,6 +1028,8 @@
if (isInstField) {
CXXScopeSpec &SS = D.getCXXScopeSpec();
+ if (DefLoc.isValid())
+ Diag(DefLoc, diag::err_default_special_members);
if (SS.isSet() && !SS.isInvalid()) {
// The user provided a superfluous scope specifier inside a class
@@ -1053,7 +1055,8 @@
AS);
assert(Member && "HandleField never returns null");
} else {
- Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition);
+ Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition,
+ DefLoc);
if (!Member) {
return 0;
}
More information about the cfe-commits
mailing list