Home | History | Annotate | Download | only in Sema
      1 //===--- SemaStmtAsm.cpp - Semantic Analysis for Asm Statements -----------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  This file implements semantic analysis for inline asm statements.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "clang/Sema/SemaInternal.h"
     15 #include "clang/AST/ExprCXX.h"
     16 #include "clang/AST/RecordLayout.h"
     17 #include "clang/AST/TypeLoc.h"
     18 #include "clang/Basic/TargetInfo.h"
     19 #include "clang/Lex/Preprocessor.h"
     20 #include "clang/Sema/Initialization.h"
     21 #include "clang/Sema/Lookup.h"
     22 #include "clang/Sema/Scope.h"
     23 #include "clang/Sema/ScopeInfo.h"
     24 #include "llvm/ADT/ArrayRef.h"
     25 #include "llvm/ADT/BitVector.h"
     26 #include "llvm/MC/MCParser/MCAsmParser.h"
     27 using namespace clang;
     28 using namespace sema;
     29 
     30 /// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
     31 /// ignore "noop" casts in places where an lvalue is required by an inline asm.
     32 /// We emulate this behavior when -fheinous-gnu-extensions is specified, but
     33 /// provide a strong guidance to not use it.
     34 ///
     35 /// This method checks to see if the argument is an acceptable l-value and
     36 /// returns false if it is a case we can handle.
     37 static bool CheckAsmLValue(const Expr *E, Sema &S) {
     38   // Type dependent expressions will be checked during instantiation.
     39   if (E->isTypeDependent())
     40     return false;
     41 
     42   if (E->isLValue())
     43     return false;  // Cool, this is an lvalue.
     44 
     45   // Okay, this is not an lvalue, but perhaps it is the result of a cast that we
     46   // are supposed to allow.
     47   const Expr *E2 = E->IgnoreParenNoopCasts(S.Context);
     48   if (E != E2 && E2->isLValue()) {
     49     if (!S.getLangOpts().HeinousExtensions)
     50       S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
     51         << E->getSourceRange();
     52     else
     53       S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
     54         << E->getSourceRange();
     55     // Accept, even if we emitted an error diagnostic.
     56     return false;
     57   }
     58 
     59   // None of the above, just randomly invalid non-lvalue.
     60   return true;
     61 }
     62 
     63 /// isOperandMentioned - Return true if the specified operand # is mentioned
     64 /// anywhere in the decomposed asm string.
     65 static bool isOperandMentioned(unsigned OpNo,
     66                          ArrayRef<GCCAsmStmt::AsmStringPiece> AsmStrPieces) {
     67   for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) {
     68     const GCCAsmStmt::AsmStringPiece &Piece = AsmStrPieces[p];
     69     if (!Piece.isOperand()) continue;
     70 
     71     // If this is a reference to the input and if the input was the smaller
     72     // one, then we have to reject this asm.
     73     if (Piece.getOperandNo() == OpNo)
     74       return true;
     75   }
     76   return false;
     77 }
     78 
     79 static bool CheckNakedParmReference(Expr *E, Sema &S) {
     80   FunctionDecl *Func = dyn_cast<FunctionDecl>(S.CurContext);
     81   if (!Func)
     82     return false;
     83   if (!Func->hasAttr<NakedAttr>())
     84     return false;
     85 
     86   SmallVector<Expr*, 4> WorkList;
     87   WorkList.push_back(E);
     88   while (WorkList.size()) {
     89     Expr *E = WorkList.pop_back_val();
     90     if (isa<CXXThisExpr>(E)) {
     91       S.Diag(E->getLocStart(), diag::err_asm_naked_this_ref);
     92       S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
     93       return true;
     94     }
     95     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
     96       if (isa<ParmVarDecl>(DRE->getDecl())) {
     97         S.Diag(DRE->getLocStart(), diag::err_asm_naked_parm_ref);
     98         S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
     99         return true;
    100       }
    101     }
    102     for (Stmt *Child : E->children()) {
    103       if (Expr *E = dyn_cast_or_null<Expr>(Child))
    104         WorkList.push_back(E);
    105     }
    106   }
    107   return false;
    108 }
    109 
    110 StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
    111                                  bool IsVolatile, unsigned NumOutputs,
    112                                  unsigned NumInputs, IdentifierInfo **Names,
    113                                  MultiExprArg constraints, MultiExprArg Exprs,
    114                                  Expr *asmString, MultiExprArg clobbers,
    115                                  SourceLocation RParenLoc) {
    116   unsigned NumClobbers = clobbers.size();
    117   StringLiteral **Constraints =
    118     reinterpret_cast<StringLiteral**>(constraints.data());
    119   StringLiteral *AsmString = cast<StringLiteral>(asmString);
    120   StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data());
    121 
    122   SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
    123 
    124   // The parser verifies that there is a string literal here.
    125   assert(AsmString->isAscii());
    126 
    127   bool ValidateConstraints = true;
    128   if (getLangOpts().CUDA) {
    129     // In CUDA mode don't verify asm constraints in device functions during host
    130     // compilation and vice versa.
    131     bool InDeviceMode = getLangOpts().CUDAIsDevice;
    132     FunctionDecl *FD = getCurFunctionDecl();
    133     bool IsDeviceFunction =
    134         FD && (FD->hasAttr<CUDADeviceAttr>() || FD->hasAttr<CUDAGlobalAttr>());
    135     ValidateConstraints = IsDeviceFunction == InDeviceMode;
    136   }
    137 
    138   for (unsigned i = 0; i != NumOutputs; i++) {
    139     StringLiteral *Literal = Constraints[i];
    140     assert(Literal->isAscii());
    141 
    142     StringRef OutputName;
    143     if (Names[i])
    144       OutputName = Names[i]->getName();
    145 
    146     TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
    147     if (ValidateConstraints &&
    148         !Context.getTargetInfo().validateOutputConstraint(Info))
    149       return StmtError(Diag(Literal->getLocStart(),
    150                             diag::err_asm_invalid_output_constraint)
    151                        << Info.getConstraintStr());
    152 
    153     ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
    154     if (ER.isInvalid())
    155       return StmtError();
    156     Exprs[i] = ER.get();
    157 
    158     // Check that the output exprs are valid lvalues.
    159     Expr *OutputExpr = Exprs[i];
    160 
    161     // Referring to parameters is not allowed in naked functions.
    162     if (CheckNakedParmReference(OutputExpr, *this))
    163       return StmtError();
    164 
    165     OutputConstraintInfos.push_back(Info);
    166 
    167     // If this is dependent, just continue.
    168     if (OutputExpr->isTypeDependent())
    169       continue;
    170 
    171     Expr::isModifiableLvalueResult IsLV =
    172         OutputExpr->isModifiableLvalue(Context, /*Loc=*/nullptr);
    173     switch (IsLV) {
    174     case Expr::MLV_Valid:
    175       // Cool, this is an lvalue.
    176       break;
    177     case Expr::MLV_ArrayType:
    178       // This is OK too.
    179       break;
    180     case Expr::MLV_LValueCast: {
    181       const Expr *LVal = OutputExpr->IgnoreParenNoopCasts(Context);
    182       if (!getLangOpts().HeinousExtensions) {
    183         Diag(LVal->getLocStart(), diag::err_invalid_asm_cast_lvalue)
    184             << OutputExpr->getSourceRange();
    185       } else {
    186         Diag(LVal->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
    187             << OutputExpr->getSourceRange();
    188       }
    189       // Accept, even if we emitted an error diagnostic.
    190       break;
    191     }
    192     case Expr::MLV_IncompleteType:
    193     case Expr::MLV_IncompleteVoidType:
    194       if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
    195                               diag::err_dereference_incomplete_type))
    196         return StmtError();
    197     default:
    198       return StmtError(Diag(OutputExpr->getLocStart(),
    199                             diag::err_asm_invalid_lvalue_in_output)
    200                        << OutputExpr->getSourceRange());
    201     }
    202 
    203     unsigned Size = Context.getTypeSize(OutputExpr->getType());
    204     if (!Context.getTargetInfo().validateOutputSize(Literal->getString(),
    205                                                     Size))
    206       return StmtError(Diag(OutputExpr->getLocStart(),
    207                             diag::err_asm_invalid_output_size)
    208                        << Info.getConstraintStr());
    209   }
    210 
    211   SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
    212 
    213   for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
    214     StringLiteral *Literal = Constraints[i];
    215     assert(Literal->isAscii());
    216 
    217     StringRef InputName;
    218     if (Names[i])
    219       InputName = Names[i]->getName();
    220 
    221     TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
    222     if (ValidateConstraints &&
    223         !Context.getTargetInfo().validateInputConstraint(
    224             OutputConstraintInfos.data(), NumOutputs, Info)) {
    225       return StmtError(Diag(Literal->getLocStart(),
    226                             diag::err_asm_invalid_input_constraint)
    227                        << Info.getConstraintStr());
    228     }
    229 
    230     ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
    231     if (ER.isInvalid())
    232       return StmtError();
    233     Exprs[i] = ER.get();
    234 
    235     Expr *InputExpr = Exprs[i];
    236 
    237     // Referring to parameters is not allowed in naked functions.
    238     if (CheckNakedParmReference(InputExpr, *this))
    239       return StmtError();
    240 
    241     // Only allow void types for memory constraints.
    242     if (Info.allowsMemory() && !Info.allowsRegister()) {
    243       if (CheckAsmLValue(InputExpr, *this))
    244         return StmtError(Diag(InputExpr->getLocStart(),
    245                               diag::err_asm_invalid_lvalue_in_input)
    246                          << Info.getConstraintStr()
    247                          << InputExpr->getSourceRange());
    248     } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
    249       llvm::APSInt Result;
    250       if (!InputExpr->EvaluateAsInt(Result, Context))
    251         return StmtError(
    252             Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
    253             << Info.getConstraintStr() << InputExpr->getSourceRange());
    254       if (Result.slt(Info.getImmConstantMin()) ||
    255           Result.sgt(Info.getImmConstantMax()))
    256         return StmtError(Diag(InputExpr->getLocStart(),
    257                               diag::err_invalid_asm_value_for_constraint)
    258                          << Result.toString(10) << Info.getConstraintStr()
    259                          << InputExpr->getSourceRange());
    260 
    261     } else {
    262       ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
    263       if (Result.isInvalid())
    264         return StmtError();
    265 
    266       Exprs[i] = Result.get();
    267     }
    268 
    269     if (Info.allowsRegister()) {
    270       if (InputExpr->getType()->isVoidType()) {
    271         return StmtError(Diag(InputExpr->getLocStart(),
    272                               diag::err_asm_invalid_type_in_input)
    273           << InputExpr->getType() << Info.getConstraintStr()
    274           << InputExpr->getSourceRange());
    275       }
    276     }
    277 
    278     InputConstraintInfos.push_back(Info);
    279 
    280     const Type *Ty = Exprs[i]->getType().getTypePtr();
    281     if (Ty->isDependentType())
    282       continue;
    283 
    284     if (!Ty->isVoidType() || !Info.allowsMemory())
    285       if (RequireCompleteType(InputExpr->getLocStart(), Exprs[i]->getType(),
    286                               diag::err_dereference_incomplete_type))
    287         return StmtError();
    288 
    289     unsigned Size = Context.getTypeSize(Ty);
    290     if (!Context.getTargetInfo().validateInputSize(Literal->getString(),
    291                                                    Size))
    292       return StmtError(Diag(InputExpr->getLocStart(),
    293                             diag::err_asm_invalid_input_size)
    294                        << Info.getConstraintStr());
    295   }
    296 
    297   // Check that the clobbers are valid.
    298   for (unsigned i = 0; i != NumClobbers; i++) {
    299     StringLiteral *Literal = Clobbers[i];
    300     assert(Literal->isAscii());
    301 
    302     StringRef Clobber = Literal->getString();
    303 
    304     if (!Context.getTargetInfo().isValidClobber(Clobber))
    305       return StmtError(Diag(Literal->getLocStart(),
    306                   diag::err_asm_unknown_register_name) << Clobber);
    307   }
    308 
    309   GCCAsmStmt *NS =
    310     new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
    311                              NumInputs, Names, Constraints, Exprs.data(),
    312                              AsmString, NumClobbers, Clobbers, RParenLoc);
    313   // Validate the asm string, ensuring it makes sense given the operands we
    314   // have.
    315   SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces;
    316   unsigned DiagOffs;
    317   if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
    318     Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
    319            << AsmString->getSourceRange();
    320     return StmtError();
    321   }
    322 
    323   // Validate constraints and modifiers.
    324   for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
    325     GCCAsmStmt::AsmStringPiece &Piece = Pieces[i];
    326     if (!Piece.isOperand()) continue;
    327 
    328     // Look for the correct constraint index.
    329     unsigned ConstraintIdx = Piece.getOperandNo();
    330     unsigned NumOperands = NS->getNumOutputs() + NS->getNumInputs();
    331 
    332     // Look for the (ConstraintIdx - NumOperands + 1)th constraint with
    333     // modifier '+'.
    334     if (ConstraintIdx >= NumOperands) {
    335       unsigned I = 0, E = NS->getNumOutputs();
    336 
    337       for (unsigned Cnt = ConstraintIdx - NumOperands; I != E; ++I)
    338         if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) {
    339           ConstraintIdx = I;
    340           break;
    341         }
    342 
    343       assert(I != E && "Invalid operand number should have been caught in "
    344                        " AnalyzeAsmString");
    345     }
    346 
    347     // Now that we have the right indexes go ahead and check.
    348     StringLiteral *Literal = Constraints[ConstraintIdx];
    349     const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
    350     if (Ty->isDependentType() || Ty->isIncompleteType())
    351       continue;
    352 
    353     unsigned Size = Context.getTypeSize(Ty);
    354     std::string SuggestedModifier;
    355     if (!Context.getTargetInfo().validateConstraintModifier(
    356             Literal->getString(), Piece.getModifier(), Size,
    357             SuggestedModifier)) {
    358       Diag(Exprs[ConstraintIdx]->getLocStart(),
    359            diag::warn_asm_mismatched_size_modifier);
    360 
    361       if (!SuggestedModifier.empty()) {
    362         auto B = Diag(Piece.getRange().getBegin(),
    363                       diag::note_asm_missing_constraint_modifier)
    364                  << SuggestedModifier;
    365         SuggestedModifier = "%" + SuggestedModifier + Piece.getString();
    366         B.AddFixItHint(FixItHint::CreateReplacement(Piece.getRange(),
    367                                                     SuggestedModifier));
    368       }
    369     }
    370   }
    371 
    372   // Validate tied input operands for type mismatches.
    373   unsigned NumAlternatives = ~0U;
    374   for (unsigned i = 0, e = OutputConstraintInfos.size(); i != e; ++i) {
    375     TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
    376     StringRef ConstraintStr = Info.getConstraintStr();
    377     unsigned AltCount = ConstraintStr.count(',') + 1;
    378     if (NumAlternatives == ~0U)
    379       NumAlternatives = AltCount;
    380     else if (NumAlternatives != AltCount)
    381       return StmtError(Diag(NS->getOutputExpr(i)->getLocStart(),
    382                             diag::err_asm_unexpected_constraint_alternatives)
    383                        << NumAlternatives << AltCount);
    384   }
    385   for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
    386     TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
    387     StringRef ConstraintStr = Info.getConstraintStr();
    388     unsigned AltCount = ConstraintStr.count(',') + 1;
    389     if (NumAlternatives == ~0U)
    390       NumAlternatives = AltCount;
    391     else if (NumAlternatives != AltCount)
    392       return StmtError(Diag(NS->getInputExpr(i)->getLocStart(),
    393                             diag::err_asm_unexpected_constraint_alternatives)
    394                        << NumAlternatives << AltCount);
    395 
    396     // If this is a tied constraint, verify that the output and input have
    397     // either exactly the same type, or that they are int/ptr operands with the
    398     // same size (int/long, int*/long, are ok etc).
    399     if (!Info.hasTiedOperand()) continue;
    400 
    401     unsigned TiedTo = Info.getTiedOperand();
    402     unsigned InputOpNo = i+NumOutputs;
    403     Expr *OutputExpr = Exprs[TiedTo];
    404     Expr *InputExpr = Exprs[InputOpNo];
    405 
    406     if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent())
    407       continue;
    408 
    409     QualType InTy = InputExpr->getType();
    410     QualType OutTy = OutputExpr->getType();
    411     if (Context.hasSameType(InTy, OutTy))
    412       continue;  // All types can be tied to themselves.
    413 
    414     // Decide if the input and output are in the same domain (integer/ptr or
    415     // floating point.
    416     enum AsmDomain {
    417       AD_Int, AD_FP, AD_Other
    418     } InputDomain, OutputDomain;
    419 
    420     if (InTy->isIntegerType() || InTy->isPointerType())
    421       InputDomain = AD_Int;
    422     else if (InTy->isRealFloatingType())
    423       InputDomain = AD_FP;
    424     else
    425       InputDomain = AD_Other;
    426 
    427     if (OutTy->isIntegerType() || OutTy->isPointerType())
    428       OutputDomain = AD_Int;
    429     else if (OutTy->isRealFloatingType())
    430       OutputDomain = AD_FP;
    431     else
    432       OutputDomain = AD_Other;
    433 
    434     // They are ok if they are the same size and in the same domain.  This
    435     // allows tying things like:
    436     //   void* to int*
    437     //   void* to int            if they are the same size.
    438     //   double to long double   if they are the same size.
    439     //
    440     uint64_t OutSize = Context.getTypeSize(OutTy);
    441     uint64_t InSize = Context.getTypeSize(InTy);
    442     if (OutSize == InSize && InputDomain == OutputDomain &&
    443         InputDomain != AD_Other)
    444       continue;
    445 
    446     // If the smaller input/output operand is not mentioned in the asm string,
    447     // then we can promote the smaller one to a larger input and the asm string
    448     // won't notice.
    449     bool SmallerValueMentioned = false;
    450 
    451     // If this is a reference to the input and if the input was the smaller
    452     // one, then we have to reject this asm.
    453     if (isOperandMentioned(InputOpNo, Pieces)) {
    454       // This is a use in the asm string of the smaller operand.  Since we
    455       // codegen this by promoting to a wider value, the asm will get printed
    456       // "wrong".
    457       SmallerValueMentioned |= InSize < OutSize;
    458     }
    459     if (isOperandMentioned(TiedTo, Pieces)) {
    460       // If this is a reference to the output, and if the output is the larger
    461       // value, then it's ok because we'll promote the input to the larger type.
    462       SmallerValueMentioned |= OutSize < InSize;
    463     }
    464 
    465     // If the smaller value wasn't mentioned in the asm string, and if the
    466     // output was a register, just extend the shorter one to the size of the
    467     // larger one.
    468     if (!SmallerValueMentioned && InputDomain != AD_Other &&
    469         OutputConstraintInfos[TiedTo].allowsRegister())
    470       continue;
    471 
    472     // Either both of the operands were mentioned or the smaller one was
    473     // mentioned.  One more special case that we'll allow: if the tied input is
    474     // integer, unmentioned, and is a constant, then we'll allow truncating it
    475     // down to the size of the destination.
    476     if (InputDomain == AD_Int && OutputDomain == AD_Int &&
    477         !isOperandMentioned(InputOpNo, Pieces) &&
    478         InputExpr->isEvaluatable(Context)) {
    479       CastKind castKind =
    480         (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
    481       InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).get();
    482       Exprs[InputOpNo] = InputExpr;
    483       NS->setInputExpr(i, InputExpr);
    484       continue;
    485     }
    486 
    487     Diag(InputExpr->getLocStart(),
    488          diag::err_asm_tying_incompatible_types)
    489       << InTy << OutTy << OutputExpr->getSourceRange()
    490       << InputExpr->getSourceRange();
    491     return StmtError();
    492   }
    493 
    494   return NS;
    495 }
    496 
    497 ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
    498                                            SourceLocation TemplateKWLoc,
    499                                            UnqualifiedId &Id,
    500                                            llvm::InlineAsmIdentifierInfo &Info,
    501                                            bool IsUnevaluatedContext) {
    502   Info.clear();
    503 
    504   if (IsUnevaluatedContext)
    505     PushExpressionEvaluationContext(UnevaluatedAbstract,
    506                                     ReuseLambdaContextDecl);
    507 
    508   ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
    509                                         /*trailing lparen*/ false,
    510                                         /*is & operand*/ false,
    511                                         /*CorrectionCandidateCallback=*/nullptr,
    512                                         /*IsInlineAsmIdentifier=*/ true);
    513 
    514   if (IsUnevaluatedContext)
    515     PopExpressionEvaluationContext();
    516 
    517   if (!Result.isUsable()) return Result;
    518 
    519   Result = CheckPlaceholderExpr(Result.get());
    520   if (!Result.isUsable()) return Result;
    521 
    522   // Referring to parameters is not allowed in naked functions.
    523   if (CheckNakedParmReference(Result.get(), *this))
    524     return ExprError();
    525 
    526   QualType T = Result.get()->getType();
    527 
    528   // For now, reject dependent types.
    529   if (T->isDependentType()) {
    530     Diag(Id.getLocStart(), diag::err_asm_incomplete_type) << T;
    531     return ExprError();
    532   }
    533 
    534   // Any sort of function type is fine.
    535   if (T->isFunctionType()) {
    536     return Result;
    537   }
    538 
    539   // Otherwise, it needs to be a complete type.
    540   if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) {
    541     return ExprError();
    542   }
    543 
    544   // Compute the type size (and array length if applicable?).
    545   Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity();
    546   if (T->isArrayType()) {
    547     const ArrayType *ATy = Context.getAsArrayType(T);
    548     Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
    549     Info.Length = Info.Size / Info.Type;
    550   }
    551 
    552   // We can work with the expression as long as it's not an r-value.
    553   if (!Result.get()->isRValue())
    554     Info.IsVarDecl = true;
    555 
    556   return Result;
    557 }
    558 
    559 bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
    560                                 unsigned &Offset, SourceLocation AsmLoc) {
    561   Offset = 0;
    562   LookupResult BaseResult(*this, &Context.Idents.get(Base), SourceLocation(),
    563                           LookupOrdinaryName);
    564 
    565   if (!LookupName(BaseResult, getCurScope()))
    566     return true;
    567 
    568   if (!BaseResult.isSingleResult())
    569     return true;
    570 
    571   const RecordType *RT = nullptr;
    572   NamedDecl *FoundDecl = BaseResult.getFoundDecl();
    573   if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
    574     RT = VD->getType()->getAs<RecordType>();
    575   else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl)) {
    576     MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
    577     RT = TD->getUnderlyingType()->getAs<RecordType>();
    578   } else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
    579     RT = TD->getTypeForDecl()->getAs<RecordType>();
    580   if (!RT)
    581     return true;
    582 
    583   if (RequireCompleteType(AsmLoc, QualType(RT, 0), 0))
    584     return true;
    585 
    586   LookupResult FieldResult(*this, &Context.Idents.get(Member), SourceLocation(),
    587                            LookupMemberName);
    588 
    589   if (!LookupQualifiedName(FieldResult, RT->getDecl()))
    590     return true;
    591 
    592   // FIXME: Handle IndirectFieldDecl?
    593   FieldDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl());
    594   if (!FD)
    595     return true;
    596 
    597   const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl());
    598   unsigned i = FD->getFieldIndex();
    599   CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i));
    600   Offset = (unsigned)Result.getQuantity();
    601 
    602   return false;
    603 }
    604 
    605 StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
    606                                 ArrayRef<Token> AsmToks,
    607                                 StringRef AsmString,
    608                                 unsigned NumOutputs, unsigned NumInputs,
    609                                 ArrayRef<StringRef> Constraints,
    610                                 ArrayRef<StringRef> Clobbers,
    611                                 ArrayRef<Expr*> Exprs,
    612                                 SourceLocation EndLoc) {
    613   bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
    614   getCurFunction()->setHasBranchProtectedScope();
    615   MSAsmStmt *NS =
    616     new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
    617                             /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
    618                             Constraints, Exprs, AsmString,
    619                             Clobbers, EndLoc);
    620   return NS;
    621 }
    622 
    623 LabelDecl *Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
    624                                        SourceLocation Location,
    625                                        bool AlwaysCreate) {
    626   LabelDecl* Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
    627                                          Location);
    628 
    629   if (Label->isMSAsmLabel()) {
    630     // If we have previously created this label implicitly, mark it as used.
    631     Label->markUsed(Context);
    632   } else {
    633     // Otherwise, insert it, but only resolve it if we have seen the label itself.
    634     std::string InternalName;
    635     llvm::raw_string_ostream OS(InternalName);
    636     // Create an internal name for the label.  The name should not be a valid mangled
    637     // name, and should be unique.  We use a dot to make the name an invalid mangled
    638     // name.
    639     OS << "__MSASMLABEL_." << MSAsmLabelNameCounter++ << "__" << ExternalLabelName;
    640     Label->setMSAsmLabel(OS.str());
    641   }
    642   if (AlwaysCreate) {
    643     // The label might have been created implicitly from a previously encountered
    644     // goto statement.  So, for both newly created and looked up labels, we mark
    645     // them as resolved.
    646     Label->setMSAsmLabelResolved();
    647   }
    648   // Adjust their location for being able to generate accurate diagnostics.
    649   Label->setLocation(Location);
    650 
    651   return Label;
    652 }
    653