Move parsing of identifiers in MS-style inline assembly into

the actual parser and support arbitrary id-expressions.

We're actually basically set up to do arbitrary expressions here
if we wanted to.

Assembly operands permit things like A::x to be written regardless
of language mode, which forces us to embellish the evaluation
context logic somewhat.  The logic here under template instantiation
is incorrect;  we need to preserve the fact that an expression was
unevaluated.  Of course, template instantiation in general is fishy
here because we have no way of delaying semantic analysis in the
MC parser.  It's all just fishy.

I've also fixed the serialization of MS asm statements.

This commit depends on an LLVM commit.

llvm-svn: 180976
This commit is contained in:
John McCall
2013-05-03 00:10:13 +00:00
parent bfa9fb134b
commit f413f5ed44
24 changed files with 857 additions and 430 deletions

View File

@@ -60,6 +60,9 @@ enum IMAKind {
/// The reference may be to an unresolved using declaration.
IMA_Unresolved,
/// The reference is a contextually-permitted abstract member reference.
IMA_Abstract,
/// The reference may be to an unresolved using declaration and the
/// context is not an instance method.
IMA_Unresolved_StaticContext,
@@ -120,19 +123,32 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
// member reference.
if (Classes.empty())
return IMA_Static;
// C++11 [expr.prim.general]p12:
// An id-expression that denotes a non-static data member or non-static
// member function of a class can only be used:
// (...)
// - if that id-expression denotes a non-static data member and it
// appears in an unevaluated operand.
//
// This rule is specific to C++11. However, we also permit this form
// in unevaluated inline assembly operands, like the operand to a SIZE.
IMAKind AbstractInstanceResult = IMA_Static; // happens to be 'false'
assert(!AbstractInstanceResult);
switch (SemaRef.ExprEvalContexts.back().Context) {
case Sema::Unevaluated:
if (isField && SemaRef.getLangOpts().CPlusPlus11)
AbstractInstanceResult = IMA_Field_Uneval_Context;
break;
bool IsCXX11UnevaluatedField = false;
if (SemaRef.getLangOpts().CPlusPlus11 && isField) {
// C++11 [expr.prim.general]p12:
// An id-expression that denotes a non-static data member or non-static
// member function of a class can only be used:
// (...)
// - if that id-expression denotes a non-static data member and it
// appears in an unevaluated operand.
const Sema::ExpressionEvaluationContextRecord& record
= SemaRef.ExprEvalContexts.back();
if (record.Context == Sema::Unevaluated)
IsCXX11UnevaluatedField = true;
case Sema::UnevaluatedAbstract:
AbstractInstanceResult = IMA_Abstract;
break;
case Sema::ConstantEvaluated:
case Sema::PotentiallyEvaluated:
case Sema::PotentiallyEvaluatedIfUsed:
break;
}
// If the current context is not an instance method, it can't be
@@ -141,8 +157,8 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
if (hasNonInstance)
return IMA_Mixed_StaticContext;
return IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context
: IMA_Error_StaticContext;
return AbstractInstanceResult ? AbstractInstanceResult
: IMA_Error_StaticContext;
}
CXXRecordDecl *contextClass;
@@ -172,8 +188,8 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
// which case it's an error if any of those members are selected).
if (isProvablyNotDerivedFrom(SemaRef, contextClass, Classes))
return hasNonInstance ? IMA_Mixed_Unrelated :
IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context :
IMA_Error_Unrelated;
AbstractInstanceResult ? AbstractInstanceResult :
IMA_Error_Unrelated;
return (hasNonInstance ? IMA_Mixed : IMA_Instance);
}
@@ -233,6 +249,7 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
<< R.getLookupNameInfo().getName();
// Fall through.
case IMA_Static:
case IMA_Abstract:
case IMA_Mixed_StaticContext:
case IMA_Unresolved_StaticContext:
if (TemplateArgs || TemplateKWLoc.isValid())