Sema: Add a flag for rejecting member pointers with incomplete base types.

Codebases that need to be compatible with the Microsoft ABI can pass
this flag to avoid issues caused by the lack of a fixed ABI for
incomplete member pointers.

Differential Revision: https://reviews.llvm.org/D47503

llvm-svn: 333498
This commit is contained in:
Peter Collingbourne 2018-05-30 03:40:04 +00:00
parent 3d9305f28b
commit 54d13b4068
8 changed files with 51 additions and 5 deletions

View File

@ -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>;

View File

@ -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,

View File

@ -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>;

View File

@ -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 &&

View File

@ -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) {

View File

@ -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());
}

View File

@ -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"

View File

@ -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;
};