summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/include/clang/Basic/LangOptions.def4
-rw-r--r--clang/include/clang/Driver/Options.td6
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp4
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp2
-rw-r--r--clang/lib/Sema/SemaType.cpp16
-rw-r--r--clang/test/Driver/complete-member-pointers.cpp7
-rw-r--r--clang/test/SemaCXX/complete-member-pointers.cpp15
8 files changed, 51 insertions, 5 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1fa66cbcfc7..b4d76ba9183 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6350,6 +6350,8 @@ def err_bad_memptr_rhs : Error<
def err_bad_memptr_lhs : Error<
"left hand operand to %0 must be a %select{|pointer to }1class "
"compatible with the right hand operand, but is %2">;
+def err_memptr_incomplete : Error<
+ "member pointer has incomplete base type %0">;
def warn_exception_caught_by_earlier_handler : Warning<
"exception of type %0 will be caught by earlier handler">,
InGroup<Exceptions>;
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 654b755f672..8605286f28c 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -247,6 +247,10 @@ ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "Op
LANGOPT(IncludeDefaultHeader, 1, 0, "Include default header file for OpenCL")
BENIGN_LANGOPT(DelayedTemplateParsing , 1, 0, "delayed template parsing")
LANGOPT(BlocksRuntimeOptional , 1, 0, "optional blocks runtime")
+LANGOPT(
+ CompleteMemberPointers, 1, 0,
+ "Require member pointer base types to be complete at the point where the "
+ "type's inheritance model would be determined under the Microsoft ABI")
ENUM_LANGOPT(GC, GCMode, 2, NonGC, "Objective-C Garbage Collection mode")
ENUM_LANGOPT(ValueVisibilityMode, Visibility, 3, DefaultVisibility,
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index bc27844b72e..ed255c97ab9 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -782,6 +782,12 @@ def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, Gr
def fparse_all_comments : Flag<["-"], "fparse-all-comments">, Group<f_clang_Group>, Flags<[CC1Option]>;
def fcommon : Flag<["-"], "fcommon">, Group<f_Group>;
def fcompile_resource_EQ : Joined<["-"], "fcompile-resource=">, Group<f_Group>;
+def fcomplete_member_pointers : Flag<["-"], "fcomplete-member-pointers">, Group<f_clang_Group>,
+ Flags<[CoreOption, CC1Option]>,
+ HelpText<"Require member pointer base types to be complete if they would be significant under the Microsoft ABI">;
+def fno_complete_member_pointers : Flag<["-"], "fno-complete-member-pointers">, Group<f_clang_Group>,
+ Flags<[CoreOption]>,
+ HelpText<"Do not require member pointer base types to be complete if they would be significant under the Microsoft ABI">;
def fconstant_cfstrings : Flag<["-"], "fconstant-cfstrings">, Group<f_Group>;
def fconstant_string_class_EQ : Joined<["-"], "fconstant-string-class=">, Group<f_Group>;
def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group<f_Group>;
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 2c0fc4e7e3d..2347cfebf0b 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -4784,6 +4784,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fforce-enable-int128");
}
+ if (Args.hasFlag(options::OPT_fcomplete_member_pointers,
+ options::OPT_fno_complete_member_pointers, false))
+ CmdArgs.push_back("-fcomplete-member-pointers");
+
// Finally add the compile command to the compilation.
if (Args.hasArg(options::OPT__SLASH_fallback) &&
Output.getType() == types::TY_Object &&
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 75d6a26cdb7..594164332ec 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2754,6 +2754,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
<< A->getAsString(Args) << A->getValue();
}
}
+
+ Opts.CompleteMemberPointers = Args.hasArg(OPT_fcomplete_member_pointers);
}
static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 7e8f9b19e3d..b5a90af39ba 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -7585,11 +7585,17 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// assert(!T->isDependentType() &&
// "Can't ask whether a dependent type is complete");
- // We lock in the inheritance model once somebody has asked us to ensure
- // that a pointer-to-member type is complete.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
- if (!MPTy->getClass()->isDependentType()) {
+ if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
+ if (!MPTy->getClass()->isDependentType()) {
+ if (getLangOpts().CompleteMemberPointers &&
+ !MPTy->getClass()->getAsCXXRecordDecl()->isBeingDefined() &&
+ RequireCompleteType(Loc, QualType(MPTy->getClass(), 0),
+ diag::err_memptr_incomplete))
+ return true;
+
+ // We lock in the inheritance model once somebody has asked us to ensure
+ // that a pointer-to-member type is complete.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
(void)isCompleteType(Loc, QualType(MPTy->getClass(), 0));
assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
}
diff --git a/clang/test/Driver/complete-member-pointers.cpp b/clang/test/Driver/complete-member-pointers.cpp
new file mode 100644
index 00000000000..6fde2e7a0ef
--- /dev/null
+++ b/clang/test/Driver/complete-member-pointers.cpp
@@ -0,0 +1,7 @@
+// RUN: %clangxx -### -c %s -o %t.o -target x86_64-unknown-linux 2>&1 | FileCheck --check-prefix=NOFLAG %s
+// RUN: %clangxx -### -c %s -o %t.o -target x86_64-unknown-linux -fcomplete-member-pointers 2>&1 | FileCheck %s
+// RUN: %clangxx -### -c %s -o %t.o -target x86_64-unknown-linux -fcomplete-member-pointers -fno-complete-member-pointers 2>&1 | FileCheck --check-prefix=NOFLAG %s
+// RUN: %clang_cl -### /c %s /Fo%t.o -target x86_64-pc-win32 -fcomplete-member-pointers 2>&1 | FileCheck %s
+
+// CHECK: "-fcomplete-member-pointers"
+// NOFLAG-NOT: "-fcomplete-member-pointers"
diff --git a/clang/test/SemaCXX/complete-member-pointers.cpp b/clang/test/SemaCXX/complete-member-pointers.cpp
new file mode 100644
index 00000000000..942bb703a92
--- /dev/null
+++ b/clang/test/SemaCXX/complete-member-pointers.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -verify -fsyntax-only -fcomplete-member-pointers %s
+
+struct S; // expected-note {{forward declaration of 'S'}}
+typedef int S::*t;
+t foo; // expected-error {{member pointer has incomplete base type 'S'}}
+
+struct S2 {
+ int S2::*foo;
+};
+int S2::*bar;
+
+template <typename T>
+struct S3 {
+ int T::*foo;
+};
OpenPOWER on IntegriCloud