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"
27using namespace clang;
28using 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.
37static 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.
65static 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
79static 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
110StmtResult 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
497ExprResult 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
559bool 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
605StmtResult 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
623LabelDecl *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