Enable clang to continue to parse libstdc++4.6 and stlport after r210091.
r210091 made initialization checking more strict in c++11 mode. LWG2193 is about changing standard libraries to still be valid under these new rules, but older libstdc++ (e.g. libstdc++4.6 in -D_GLIBCXX_DEBUG=1 mode, or stlport) do not implement that yet. So fall back to the C++03 semantics for container classes in system headers below the std namespace. llvm-svn: 212238
This commit is contained in:
parent
ae7127fb32
commit
bcb70eee1a
|
@ -2128,6 +2128,10 @@ def err_attribute_dllimport_static_field_definition : Error<
|
|||
def warn_attribute_dllimport_static_field_definition : Warning<
|
||||
"definition of dllimport static field">,
|
||||
InGroup<DiagGroup<"dllimport-static-field-def">>;
|
||||
def warn_invalid_initializer_from_system_header : Warning<
|
||||
"invalid constructor form class in system header, should not be explicit">,
|
||||
InGroup<DiagGroup<"invalid-initializer-from-system-header">>;
|
||||
def note_used_in_initialization_here : Note<"used in initialization here">;
|
||||
def err_attribute_dll_member_of_dll_class : Error<
|
||||
"attribute %q0 cannot be applied to member of %q1 class">;
|
||||
def warn_attribute_dll_instantiated_base_class : Warning<
|
||||
|
|
|
@ -353,8 +353,9 @@ ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef,
|
|||
// If there are fewer initializer-clauses in the list than there are
|
||||
// members in the aggregate, then each member not explicitly initialized
|
||||
// ...
|
||||
if (SemaRef.getLangOpts().CPlusPlus11 &&
|
||||
Entity.getType()->getBaseElementTypeUnsafe()->isRecordType()) {
|
||||
bool EmptyInitList = SemaRef.getLangOpts().CPlusPlus11 &&
|
||||
Entity.getType()->getBaseElementTypeUnsafe()->isRecordType();
|
||||
if (EmptyInitList) {
|
||||
// C++1y / DR1070:
|
||||
// shall be initialized [...] from an empty initializer list.
|
||||
//
|
||||
|
@ -376,6 +377,56 @@ ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef,
|
|||
}
|
||||
|
||||
InitializationSequence InitSeq(SemaRef, Entity, Kind, SubInit);
|
||||
// libstdc++4.6 marks the vector default constructor as explicit in
|
||||
// _GLIBCXX_DEBUG mode, so recover using the C++03 logic in that case.
|
||||
// stlport does so too. Look for std::__debug for libstdc++, and for
|
||||
// std:: for stlport. This is effectively a compiler-side implementation of
|
||||
// LWG2193.
|
||||
if (!InitSeq && EmptyInitList && InitSeq.getFailureKind() ==
|
||||
InitializationSequence::FK_ExplicitConstructor) {
|
||||
OverloadCandidateSet::iterator Best;
|
||||
OverloadingResult O =
|
||||
InitSeq.getFailedCandidateSet()
|
||||
.BestViableFunction(SemaRef, Kind.getLocation(), Best);
|
||||
(void)O;
|
||||
assert(O == OR_Success && "Inconsistent overload resolution");
|
||||
CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
|
||||
CXXRecordDecl *R = CtorDecl->getParent();
|
||||
|
||||
if (CtorDecl->getMinRequiredArguments() == 0 &&
|
||||
CtorDecl->isExplicit() && R->getDeclName() &&
|
||||
SemaRef.SourceMgr.isInSystemHeader(CtorDecl->getLocation())) {
|
||||
|
||||
|
||||
bool IsInStd = false;
|
||||
for (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(R->getDeclContext());
|
||||
ND && !IsInStd;
|
||||
ND = dyn_cast<NamespaceDecl>(ND->getLexicalParent())) {
|
||||
if (SemaRef.getStdNamespace()->InEnclosingNamespaceSetOf(ND))
|
||||
IsInStd = true;
|
||||
}
|
||||
|
||||
if (IsInStd && llvm::StringSwitch<bool>(R->getName())
|
||||
.Cases("basic_string", "deque", "forward_list", true)
|
||||
.Cases("list", "map", "multimap", "multiset", true)
|
||||
.Cases("priority_queue", "queue", "set", "stack", true)
|
||||
.Cases("unordered_map", "unordered_set", "vector", true)
|
||||
.Default(false)) {
|
||||
InitSeq.InitializeFrom(
|
||||
SemaRef, Entity,
|
||||
InitializationKind::CreateValue(Loc, Loc, Loc, true),
|
||||
MultiExprArg(), /*TopLevelOfInitList=*/false);
|
||||
// Emit a warning for this. System header warnings aren't shown
|
||||
// by default, but people working on system headers should see it.
|
||||
if (!VerifyOnly) {
|
||||
SemaRef.Diag(CtorDecl->getLocation(),
|
||||
diag::warn_invalid_initializer_from_system_header);
|
||||
SemaRef.Diag(Entity.getDecl()->getLocation(),
|
||||
diag::note_used_in_initialization_here);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!InitSeq) {
|
||||
if (!VerifyOnly) {
|
||||
InitSeq.Diagnose(SemaRef, Entity, Kind, SubInit);
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wsystem-headers %s
|
||||
|
||||
// libstdc++4.6 in debug mode has explicit default constructors.
|
||||
// stlport has this for all containers.
|
||||
#ifdef BE_THE_HEADER
|
||||
#pragma clang system_header
|
||||
namespace std {
|
||||
namespace __debug {
|
||||
template <class T>
|
||||
class vector {
|
||||
public:
|
||||
explicit vector() {} // expected-warning{{should not be explicit}}
|
||||
};
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
#define BE_THE_HEADER
|
||||
#include __FILE__
|
||||
|
||||
struct { int a, b; std::__debug::vector<int> c; } e[] = { {1, 1} }; // expected-note{{used in initialization here}}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue