summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td7
-rw-r--r--include/clang/Sema/Initialization.h15
-rw-r--r--lib/Sema/SemaInit.cpp64
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp4
-rw-r--r--test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp4
-rw-r--r--test/CXX/dcl.decl/dcl.init/p6.cpp6
-rw-r--r--test/CXX/drs/dr0xx.cpp2
-rw-r--r--test/CXX/drs/dr4xx.cpp4
-rw-r--r--test/FixIt/fixit.cpp8
-rw-r--r--test/SemaCXX/attr-selectany.cpp12
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp2
-rw-r--r--test/SemaCXX/constexpr-value-init.cpp6
-rw-r--r--test/SemaCXX/cxx0x-cursory-default-delete.cpp2
-rw-r--r--test/SemaCXX/cxx1y-variable-templates_in_class.cpp4
14 files changed, 97 insertions, 43 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 4ac4c19a58..d4ec5cc277 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5470,8 +5470,11 @@ def err_address_space_qualified_delete : Error<
def err_default_init_const : Error<
"default initialization of an object of const type %0"
"%select{| without a user-provided default constructor}1">;
-def note_add_initializer : Note<
- "add an explicit initializer to initialize %0">;
+def ext_default_init_const : ExtWarn<
+ "default initialization of an object of const type %0"
+ "%select{| without a user-provided default constructor}1 "
+ "is a Microsoft extension">,
+ InGroup<Microsoft>;
def err_delete_operand : Error<"cannot delete expression of type %0">;
def ext_delete_void_ptr_operand : ExtWarn<
"cannot delete expression with pointer-to-'void' type %0">,
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
index 6110d22bb9..74de00ff25 100644
--- a/include/clang/Sema/Initialization.h
+++ b/include/clang/Sema/Initialization.h
@@ -844,6 +844,21 @@ private:
/// \brief The incomplete type that caused a failure.
QualType FailedIncompleteType;
+
+ /// \brief The fixit that needs to be applied to make this initialization
+ /// succeed.
+ std::string ZeroInitializationFixit;
+ SourceLocation ZeroInitializationFixitLoc;
+
+public:
+ /// \brief Call for initializations are invalid but that would be valid
+ /// zero initialzations if Fixit was applied.
+ void SetZeroInitializationFixit(const std::string& Fixit, SourceLocation L) {
+ ZeroInitializationFixit = Fixit;
+ ZeroInitializationFixitLoc = L;
+ }
+
+private:
/// \brief Prints a follow-up note that highlights the location of
/// the initialized entity, if it's remote.
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 75ccc4ea76..3ee1a7f8ad 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -3101,6 +3101,28 @@ void InitializationSequence::SetOverloadFailure(FailureKind Failure,
// Attempt initialization
//===----------------------------------------------------------------------===//
+/// Tries to add a zero initializer. Returns true if that worked.
+static bool
+maybeRecoverWithZeroInitialization(Sema &S, InitializationSequence &Sequence,
+ const InitializedEntity &Entity) {
+ if (Entity.getKind() != InitializedEntity::EK_Variable)
+ return false;
+
+ VarDecl *VD = cast<VarDecl>(Entity.getDecl());
+ if (VD->getInit() || VD->getLocEnd().isMacroID())
+ return false;
+
+ QualType VariableTy = VD->getType().getCanonicalType();
+ SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd());
+ std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
+ if (!Init.empty()) {
+ Sequence.AddZeroInitializationStep(Entity.getType());
+ Sequence.SetZeroInitializationFixit(Init, Loc);
+ return true;
+ }
+ return false;
+}
+
static void MaybeProduceObjCObject(Sema &S,
InitializationSequence &Sequence,
const InitializedEntity &Entity) {
@@ -3339,7 +3361,8 @@ static void TryConstructorInitialization(Sema &S,
if (Kind.getKind() == InitializationKind::IK_Default &&
Entity.getType().isConstQualified() &&
!cast<CXXConstructorDecl>(Best->Function)->isUserProvided()) {
- Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+ if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity))
+ Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
return;
}
@@ -4231,7 +4254,8 @@ static void TryDefaultInitialization(Sema &S,
// a const-qualified type T, T shall be a class type with a user-provided
// default constructor.
if (DestType.isConstQualified() && S.getLangOpts().CPlusPlus) {
- Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+ if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity))
+ Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
return;
}
@@ -5749,6 +5773,21 @@ InitializationSequence::Perform(Sema &S,
Diagnose(S, Entity, Kind, Args);
return ExprError();
}
+ if (!ZeroInitializationFixit.empty()) {
+ unsigned DiagID = diag::err_default_init_const;
+ if (Decl *D = Entity.getDecl())
+ if (S.getLangOpts().MSVCCompat && D->hasAttr<SelectAnyAttr>())
+ DiagID = diag::ext_default_init_const;
+
+ // The initialization would have succeeded with this fixit. Since the fixit
+ // is on the error, we need to build a valid AST in this case, so this isn't
+ // handled in the Failed() branch above.
+ QualType DestType = Entity.getType();
+ S.Diag(Kind.getLocation(), DiagID)
+ << DestType << (bool)DestType->getAs<RecordType>()
+ << FixItHint::CreateInsertion(ZeroInitializationFixitLoc,
+ ZeroInitializationFixit);
+ }
if (getKind() == DependentSequence) {
// If the declaration is a non-dependent, incomplete array type
@@ -6549,26 +6588,6 @@ static void diagnoseListInit(Sema &S, const InitializedEntity &Entity,
"Inconsistent init list check result.");
}
-/// Prints a fixit for adding a null initializer for |Entity|. Call this only
-/// right after emitting a diagnostic.
-static void maybeEmitZeroInitializationFixit(Sema &S,
- InitializationSequence &Sequence,
- const InitializedEntity &Entity) {
- if (Entity.getKind() != InitializedEntity::EK_Variable)
- return;
-
- VarDecl *VD = cast<VarDecl>(Entity.getDecl());
- if (VD->getInit() || VD->getLocEnd().isMacroID())
- return;
-
- QualType VariableTy = VD->getType().getCanonicalType();
- SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd());
- std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
-
- S.Diag(Loc, diag::note_add_initializer)
- << VD << FixItHint::CreateInsertion(Loc, Init);
-}
-
bool InitializationSequence::Diagnose(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -6900,7 +6919,6 @@ bool InitializationSequence::Diagnose(Sema &S,
} else {
S.Diag(Kind.getLocation(), diag::err_default_init_const)
<< DestType << (bool)DestType->getAs<RecordType>();
- maybeEmitZeroInitializationFixit(S, *this, Entity);
}
break;
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
index 5f102e7458..0aaedcc076 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
@@ -17,7 +17,7 @@ extern int (*const d)(int);
// A variable declaration which uses the constexpr specifier shall have an
// initializer and shall be initialized by a constant expression.
-constexpr int ni1; // expected-error {{default initialization of an object of const type 'const int'}} expected-note {{add an explicit initializer to initialize 'ni1'}}
+constexpr int ni1; // expected-error {{default initialization of an object of const type 'const int'}}
constexpr struct C { C(); } ni2; // expected-error {{cannot have non-literal type 'const struct C'}} expected-note 3{{has no constexpr constructors}}
constexpr double &ni3; // expected-error {{declaration of reference variable 'ni3' requires an initializer}}
@@ -34,4 +34,4 @@ struct pixel {
int x, y;
};
constexpr pixel ur = { 1294, 1024 }; // ok
-constexpr pixel origin; // expected-error {{default initialization of an object of const type 'const pixel' without a user-provided default constructor}} expected-note {{add an explicit initializer to initialize 'origin'}}
+constexpr pixel origin; // expected-error {{default initialization of an object of const type 'const pixel' without a user-provided default constructor}}
diff --git a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
index 81876192ca..5cf281c185 100644
--- a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
+++ b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
@@ -36,7 +36,7 @@ struct S3 {
constexpr S3 s3a = S3(0);
constexpr S3 s3b = s3a;
constexpr S3 s3c = S3();
-constexpr S3 s3d; // expected-error {{default initialization of an object of const type 'const S3' without a user-provided default constructor}} expected-note{{add an explicit initializer to initialize 's3d'}}
+constexpr S3 s3d; // expected-error {{default initialization of an object of const type 'const S3' without a user-provided default constructor}}
struct S4 {
S4() = default;
@@ -119,6 +119,6 @@ namespace PR13492 {
};
void f() {
- const B b; // expected-error {{default initialization of an object of const type 'const PR13492::B' without a user-provided default constructor}} expected-note {{add an explicit initializer to initialize 'b'}}
+ const B b; // expected-error {{default initialization of an object of const type 'const PR13492::B' without a user-provided default constructor}}
}
}
diff --git a/test/CXX/dcl.decl/dcl.init/p6.cpp b/test/CXX/dcl.decl/dcl.init/p6.cpp
index 76b7e7625d..e404a1ebc1 100644
--- a/test/CXX/dcl.decl/dcl.init/p6.cpp
+++ b/test/CXX/dcl.decl/dcl.init/p6.cpp
@@ -10,15 +10,15 @@ struct NoUserDefault : public MakeNonPOD { };
struct HasUserDefault { HasUserDefault(); };
void test_const_default_init() {
- const NoUserDefault x1; // expected-error{{default initialization of an object of const type 'const NoUserDefault' without a user-provided default constructor}} expected-note {{add an explicit initializer to initialize 'x1'}}
+ const NoUserDefault x1; // expected-error{{default initialization of an object of const type 'const NoUserDefault' without a user-provided default constructor}}
const HasUserDefault x2;
- const int x3; // expected-error{{default initialization of an object of const type 'const int'}} expected-note{{add an explicit initializer to initialize 'x3'}}
+ const int x3; // expected-error{{default initialization of an object of const type 'const int'}}
}
// rdar://8501008
struct s0 {};
struct s1 { static const s0 foo; };
-const struct s0 s1::foo; // expected-error{{default initialization of an object of const type 'const struct s0' without a user-provided default constructor}} expected-note {{add an explicit initializer to initialize 'foo'}}
+const struct s0 s1::foo; // expected-error{{default initialization of an object of const type 'const struct s0' without a user-provided default constructor}}
template<typename T>
struct s2 {
diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp
index 8a4334f875..6119f3d306 100644
--- a/test/CXX/drs/dr0xx.cpp
+++ b/test/CXX/drs/dr0xx.cpp
@@ -864,7 +864,7 @@ namespace dr77 { // dr77: yes
namespace dr78 { // dr78: sup ????
// Under DR78, this is valid, because 'k' has static storage duration, so is
// zero-initialized.
- const int k; // expected-error {{default initialization of an object of const}} expected-note{{add an explicit initializer to initialize 'k'}}
+ const int k; // expected-error {{default initialization of an object of const}}
}
// dr79: na
diff --git a/test/CXX/drs/dr4xx.cpp b/test/CXX/drs/dr4xx.cpp
index 42c6774dd1..bbe5ee6faa 100644
--- a/test/CXX/drs/dr4xx.cpp
+++ b/test/CXX/drs/dr4xx.cpp
@@ -1202,9 +1202,9 @@ namespace dr497 { // dr497: yes
struct S {
mutable int i;
};
- const S cs; // expected-error {{default initialization}} expected-note {{add an explicit initializer}}
+ const S cs; // expected-error {{default initialization}}
int S::*pm = &S::i;
- cs.*pm = 88;
+ cs.*pm = 88; // expected-error {{not assignable}}
}
void after() {
diff --git a/test/FixIt/fixit.cpp b/test/FixIt/fixit.cpp
index 6c2fb7faf1..512713aa52 100644
--- a/test/FixIt/fixit.cpp
+++ b/test/FixIt/fixit.cpp
@@ -387,3 +387,11 @@ struct conversion_operator {
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:32}:""
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:44-[[@LINE-2]]:44}:" conversion_operator::* const"
};
+
+struct const_zero_init {
+ int a;
+};
+const const_zero_init czi; // expected-error {{default initialization of an object of const type 'const const_zero_init'}}
+// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:26-[[@LINE-1]]:26}:"{}"
+int use_czi = czi.a;
+
diff --git a/test/SemaCXX/attr-selectany.cpp b/test/SemaCXX/attr-selectany.cpp
index c27a915921..7d9cf7aea4 100644
--- a/test/SemaCXX/attr-selectany.cpp
+++ b/test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
// MSVC produces similar diagnostics.
__declspec(selectany) void foo() { } // expected-error{{'selectany' can only be applied to data items with external linkage}}
@@ -34,3 +34,13 @@ __declspec(selectany) X x(1);
namespace { class Internal {}; }
__declspec(selectany) auto x8 = Internal(); // expected-error {{'selectany' can only be applied to data items with external linkage}}
+
+
+// The D3D11 headers do something like this. MSVC doesn't error on this at
+// all, even without the __declspec(selectany), in violation of the standard.
+// We fall back to a warning for selectany to accept headers.
+struct SomeStruct {};
+extern const __declspec(selectany) SomeStruct some_struct; // expected-warning {{default initialization of an object of const type 'const SomeStruct' without a user-provided default constructor is a Microsoft extension}}
+
+// Without selectany, this should stay an error.
+const SomeStruct some_struct2; // expected-error {{default initialization of an object of const type 'const SomeStruct' without a user-provided default constructor}}
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index 9c62e9eb6d..3a1f6c6bd1 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1179,7 +1179,7 @@ namespace ExternConstexpr {
void f() {
extern constexpr int i; // expected-error {{constexpr variable declaration must be a definition}}
constexpr int j = 0;
- constexpr int k; // expected-error {{default initialization of an object of const type}} expected-note{{add an explicit initializer to initialize 'k'}}
+ constexpr int k; // expected-error {{default initialization of an object of const type}}
}
}
diff --git a/test/SemaCXX/constexpr-value-init.cpp b/test/SemaCXX/constexpr-value-init.cpp
index 3657c18ddb..0651111335 100644
--- a/test/SemaCXX/constexpr-value-init.cpp
+++ b/test/SemaCXX/constexpr-value-init.cpp
@@ -14,7 +14,7 @@ void f() {
constexpr A a; // expected-error {{constant expression}} expected-note {{in call to 'A()'}}
}
-constexpr B b1; // expected-error {{without a user-provided default constructor}} expected-note {{add an explicit initializer to initialize 'b1'}}
+constexpr B b1; // expected-error {{without a user-provided default constructor}}
constexpr B b2 = B(); // ok
static_assert(b2.a.a == 1, "");
static_assert(b2.a.b == 2, "");
@@ -23,9 +23,9 @@ struct C {
int c;
};
struct D : C { int d; };
-constexpr C c1; // expected-error {{without a user-provided default constructor}} expected-note{{add an explicit initializer to initialize 'c1'}}
+constexpr C c1; // expected-error {{without a user-provided default constructor}}
constexpr C c2 = C(); // ok
-constexpr D d1; // expected-error {{without a user-provided default constructor}} expected-note{{add an explicit initializer to initialize 'd1'}}
+constexpr D d1; // expected-error {{without a user-provided default constructor}}
constexpr D d2 = D(); // ok with DR1452
static_assert(D().c == 0, "");
static_assert(D().d == 0, "");
diff --git a/test/SemaCXX/cxx0x-cursory-default-delete.cpp b/test/SemaCXX/cxx0x-cursory-default-delete.cpp
index e333403af2..dfca17ad7c 100644
--- a/test/SemaCXX/cxx0x-cursory-default-delete.cpp
+++ b/test/SemaCXX/cxx0x-cursory-default-delete.cpp
@@ -25,7 +25,7 @@ void fn1 () {
non_const_copy ncc2 = ncc;
ncc = ncc2;
const non_const_copy cncc{};
- const non_const_copy cncc1; // expected-error {{default initialization of an object of const type 'const non_const_copy' without a user-provided default constructor}} expected-note {{add an explicit initializer to initialize 'cncc1'}}
+ const non_const_copy cncc1; // expected-error {{default initialization of an object of const type 'const non_const_copy' without a user-provided default constructor}}
non_const_copy ncc3 = cncc; // expected-error {{no matching}}
ncc = cncc; // expected-error {{no viable overloaded}}
};
diff --git a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
index 93a2095c9b..9ff73daa82 100644
--- a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -58,13 +58,13 @@ namespace out_of_line {
template<typename T, typename T0> static CONST T b = T(100);
template<typename T> static CONST T b<T,int>;
};
- template<typename T, typename T0> CONST T B4::a; // expected-error {{default initialization of an object of const type 'const int'}} expected-note {{add an explicit initializer to initialize 'a<int, char>'}}
+ template<typename T, typename T0> CONST T B4::a; // expected-error {{default initialization of an object of const type 'const int'}}
template<typename T> CONST T B4::a<T,int>;
template CONST int B4::a<int,char>; // expected-note {{in instantiation of}}
template CONST int B4::a<int,int>;
template<typename T, typename T0> CONST T B4::b;
- template<typename T> CONST T B4::b<T,int>; // expected-error {{default initialization of an object of const type 'const int'}} expected-note {{add an explicit initializer to initialize 'b<int, int>'}}
+ template<typename T> CONST T B4::b<T,int>; // expected-error {{default initialization of an object of const type 'const int'}}
template CONST int B4::b<int,char>;
template CONST int B4::b<int,int>; // expected-note {{in instantiation of}}
}