1243791Sdim//===--- SemaStmtAsm.cpp - Semantic Analysis for Asm Statements -----------===//
2243791Sdim//
3243791Sdim//                     The LLVM Compiler Infrastructure
4243791Sdim//
5243791Sdim// This file is distributed under the University of Illinois Open Source
6243791Sdim// License. See LICENSE.TXT for details.
7243791Sdim//
8243791Sdim//===----------------------------------------------------------------------===//
9243791Sdim//
10243791Sdim//  This file implements semantic analysis for inline asm statements.
11243791Sdim//
12243791Sdim//===----------------------------------------------------------------------===//
13243791Sdim
14243791Sdim#include "clang/Sema/SemaInternal.h"
15243791Sdim#include "clang/AST/RecordLayout.h"
16243791Sdim#include "clang/AST/TypeLoc.h"
17252723Sdim#include "clang/Basic/TargetInfo.h"
18243791Sdim#include "clang/Lex/Preprocessor.h"
19252723Sdim#include "clang/Sema/Initialization.h"
20252723Sdim#include "clang/Sema/Lookup.h"
21252723Sdim#include "clang/Sema/Scope.h"
22252723Sdim#include "clang/Sema/ScopeInfo.h"
23243791Sdim#include "llvm/ADT/ArrayRef.h"
24243791Sdim#include "llvm/ADT/BitVector.h"
25243791Sdimusing namespace clang;
26243791Sdimusing namespace sema;
27243791Sdim
28243791Sdim/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
29243791Sdim/// ignore "noop" casts in places where an lvalue is required by an inline asm.
30243791Sdim/// We emulate this behavior when -fheinous-gnu-extensions is specified, but
31243791Sdim/// provide a strong guidance to not use it.
32243791Sdim///
33243791Sdim/// This method checks to see if the argument is an acceptable l-value and
34243791Sdim/// returns false if it is a case we can handle.
35243791Sdimstatic bool CheckAsmLValue(const Expr *E, Sema &S) {
36243791Sdim  // Type dependent expressions will be checked during instantiation.
37243791Sdim  if (E->isTypeDependent())
38243791Sdim    return false;
39243791Sdim
40243791Sdim  if (E->isLValue())
41243791Sdim    return false;  // Cool, this is an lvalue.
42243791Sdim
43243791Sdim  // Okay, this is not an lvalue, but perhaps it is the result of a cast that we
44243791Sdim  // are supposed to allow.
45243791Sdim  const Expr *E2 = E->IgnoreParenNoopCasts(S.Context);
46243791Sdim  if (E != E2 && E2->isLValue()) {
47243791Sdim    if (!S.getLangOpts().HeinousExtensions)
48243791Sdim      S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
49243791Sdim        << E->getSourceRange();
50243791Sdim    else
51243791Sdim      S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
52243791Sdim        << E->getSourceRange();
53243791Sdim    // Accept, even if we emitted an error diagnostic.
54243791Sdim    return false;
55243791Sdim  }
56243791Sdim
57243791Sdim  // None of the above, just randomly invalid non-lvalue.
58243791Sdim  return true;
59243791Sdim}
60243791Sdim
61243791Sdim/// isOperandMentioned - Return true if the specified operand # is mentioned
62243791Sdim/// anywhere in the decomposed asm string.
63243791Sdimstatic bool isOperandMentioned(unsigned OpNo,
64243791Sdim                         ArrayRef<GCCAsmStmt::AsmStringPiece> AsmStrPieces) {
65243791Sdim  for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) {
66243791Sdim    const GCCAsmStmt::AsmStringPiece &Piece = AsmStrPieces[p];
67243791Sdim    if (!Piece.isOperand()) continue;
68243791Sdim
69243791Sdim    // If this is a reference to the input and if the input was the smaller
70243791Sdim    // one, then we have to reject this asm.
71243791Sdim    if (Piece.getOperandNo() == OpNo)
72243791Sdim      return true;
73243791Sdim  }
74243791Sdim  return false;
75243791Sdim}
76243791Sdim
77243791SdimStmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
78243791Sdim                                 bool IsVolatile, unsigned NumOutputs,
79243791Sdim                                 unsigned NumInputs, IdentifierInfo **Names,
80263509Sdim                                 MultiExprArg constraints, MultiExprArg Exprs,
81243791Sdim                                 Expr *asmString, MultiExprArg clobbers,
82243791Sdim                                 SourceLocation RParenLoc) {
83243791Sdim  unsigned NumClobbers = clobbers.size();
84243791Sdim  StringLiteral **Constraints =
85243791Sdim    reinterpret_cast<StringLiteral**>(constraints.data());
86243791Sdim  StringLiteral *AsmString = cast<StringLiteral>(asmString);
87243791Sdim  StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data());
88243791Sdim
89243791Sdim  SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
90243791Sdim
91243791Sdim  // The parser verifies that there is a string literal here.
92243791Sdim  if (!AsmString->isAscii())
93243791Sdim    return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character)
94243791Sdim      << AsmString->getSourceRange());
95243791Sdim
96243791Sdim  for (unsigned i = 0; i != NumOutputs; i++) {
97243791Sdim    StringLiteral *Literal = Constraints[i];
98243791Sdim    if (!Literal->isAscii())
99243791Sdim      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
100243791Sdim        << Literal->getSourceRange());
101243791Sdim
102243791Sdim    StringRef OutputName;
103243791Sdim    if (Names[i])
104243791Sdim      OutputName = Names[i]->getName();
105243791Sdim
106243791Sdim    TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
107243791Sdim    if (!Context.getTargetInfo().validateOutputConstraint(Info))
108243791Sdim      return StmtError(Diag(Literal->getLocStart(),
109243791Sdim                            diag::err_asm_invalid_output_constraint)
110243791Sdim                       << Info.getConstraintStr());
111243791Sdim
112243791Sdim    // Check that the output exprs are valid lvalues.
113243791Sdim    Expr *OutputExpr = Exprs[i];
114252723Sdim    if (CheckAsmLValue(OutputExpr, *this))
115243791Sdim      return StmtError(Diag(OutputExpr->getLocStart(),
116252723Sdim                            diag::err_asm_invalid_lvalue_in_output)
117252723Sdim                       << OutputExpr->getSourceRange());
118243791Sdim
119252723Sdim    if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
120252723Sdim                            diag::err_dereference_incomplete_type))
121252723Sdim      return StmtError();
122252723Sdim
123243791Sdim    OutputConstraintInfos.push_back(Info);
124243791Sdim  }
125243791Sdim
126243791Sdim  SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
127243791Sdim
128243791Sdim  for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
129243791Sdim    StringLiteral *Literal = Constraints[i];
130243791Sdim    if (!Literal->isAscii())
131243791Sdim      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
132243791Sdim        << Literal->getSourceRange());
133243791Sdim
134243791Sdim    StringRef InputName;
135243791Sdim    if (Names[i])
136243791Sdim      InputName = Names[i]->getName();
137243791Sdim
138243791Sdim    TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
139243791Sdim    if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(),
140243791Sdim                                                NumOutputs, Info)) {
141243791Sdim      return StmtError(Diag(Literal->getLocStart(),
142243791Sdim                            diag::err_asm_invalid_input_constraint)
143243791Sdim                       << Info.getConstraintStr());
144243791Sdim    }
145243791Sdim
146243791Sdim    Expr *InputExpr = Exprs[i];
147243791Sdim
148243791Sdim    // Only allow void types for memory constraints.
149243791Sdim    if (Info.allowsMemory() && !Info.allowsRegister()) {
150243791Sdim      if (CheckAsmLValue(InputExpr, *this))
151243791Sdim        return StmtError(Diag(InputExpr->getLocStart(),
152243791Sdim                              diag::err_asm_invalid_lvalue_in_input)
153243791Sdim                         << Info.getConstraintStr()
154243791Sdim                         << InputExpr->getSourceRange());
155243791Sdim    }
156243791Sdim
157243791Sdim    if (Info.allowsRegister()) {
158243791Sdim      if (InputExpr->getType()->isVoidType()) {
159243791Sdim        return StmtError(Diag(InputExpr->getLocStart(),
160243791Sdim                              diag::err_asm_invalid_type_in_input)
161243791Sdim          << InputExpr->getType() << Info.getConstraintStr()
162243791Sdim          << InputExpr->getSourceRange());
163243791Sdim      }
164243791Sdim    }
165243791Sdim
166243791Sdim    ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
167243791Sdim    if (Result.isInvalid())
168243791Sdim      return StmtError();
169243791Sdim
170243791Sdim    Exprs[i] = Result.take();
171243791Sdim    InputConstraintInfos.push_back(Info);
172252723Sdim
173252723Sdim    const Type *Ty = Exprs[i]->getType().getTypePtr();
174252723Sdim    if (Ty->isDependentType())
175252723Sdim      continue;
176252723Sdim
177252723Sdim    if (!Ty->isVoidType() || !Info.allowsMemory())
178252723Sdim      if (RequireCompleteType(InputExpr->getLocStart(), Exprs[i]->getType(),
179252723Sdim                              diag::err_dereference_incomplete_type))
180252723Sdim        return StmtError();
181252723Sdim
182252723Sdim    unsigned Size = Context.getTypeSize(Ty);
183252723Sdim    if (!Context.getTargetInfo().validateInputSize(Literal->getString(),
184252723Sdim                                                   Size))
185252723Sdim      return StmtError(Diag(InputExpr->getLocStart(),
186252723Sdim                            diag::err_asm_invalid_input_size)
187252723Sdim                       << Info.getConstraintStr());
188243791Sdim  }
189243791Sdim
190243791Sdim  // Check that the clobbers are valid.
191243791Sdim  for (unsigned i = 0; i != NumClobbers; i++) {
192243791Sdim    StringLiteral *Literal = Clobbers[i];
193243791Sdim    if (!Literal->isAscii())
194243791Sdim      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
195243791Sdim        << Literal->getSourceRange());
196243791Sdim
197243791Sdim    StringRef Clobber = Literal->getString();
198243791Sdim
199243791Sdim    if (!Context.getTargetInfo().isValidClobber(Clobber))
200243791Sdim      return StmtError(Diag(Literal->getLocStart(),
201243791Sdim                  diag::err_asm_unknown_register_name) << Clobber);
202243791Sdim  }
203243791Sdim
204243791Sdim  GCCAsmStmt *NS =
205243791Sdim    new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
206263509Sdim                             NumInputs, Names, Constraints, Exprs.data(),
207263509Sdim                             AsmString, NumClobbers, Clobbers, RParenLoc);
208243791Sdim  // Validate the asm string, ensuring it makes sense given the operands we
209243791Sdim  // have.
210243791Sdim  SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces;
211243791Sdim  unsigned DiagOffs;
212243791Sdim  if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
213243791Sdim    Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
214243791Sdim           << AsmString->getSourceRange();
215243791Sdim    return StmtError();
216243791Sdim  }
217243791Sdim
218243791Sdim  // Validate constraints and modifiers.
219243791Sdim  for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
220243791Sdim    GCCAsmStmt::AsmStringPiece &Piece = Pieces[i];
221243791Sdim    if (!Piece.isOperand()) continue;
222243791Sdim
223243791Sdim    // Look for the correct constraint index.
224243791Sdim    unsigned Idx = 0;
225243791Sdim    unsigned ConstraintIdx = 0;
226243791Sdim    for (unsigned i = 0, e = NS->getNumOutputs(); i != e; ++i, ++ConstraintIdx) {
227243791Sdim      TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
228243791Sdim      if (Idx == Piece.getOperandNo())
229243791Sdim        break;
230243791Sdim      ++Idx;
231243791Sdim
232243791Sdim      if (Info.isReadWrite()) {
233243791Sdim        if (Idx == Piece.getOperandNo())
234243791Sdim          break;
235243791Sdim        ++Idx;
236243791Sdim      }
237243791Sdim    }
238243791Sdim
239243791Sdim    for (unsigned i = 0, e = NS->getNumInputs(); i != e; ++i, ++ConstraintIdx) {
240243791Sdim      TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
241243791Sdim      if (Idx == Piece.getOperandNo())
242243791Sdim        break;
243243791Sdim      ++Idx;
244243791Sdim
245243791Sdim      if (Info.isReadWrite()) {
246243791Sdim        if (Idx == Piece.getOperandNo())
247243791Sdim          break;
248243791Sdim        ++Idx;
249243791Sdim      }
250243791Sdim    }
251243791Sdim
252243791Sdim    // Now that we have the right indexes go ahead and check.
253243791Sdim    StringLiteral *Literal = Constraints[ConstraintIdx];
254243791Sdim    const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
255243791Sdim    if (Ty->isDependentType() || Ty->isIncompleteType())
256243791Sdim      continue;
257243791Sdim
258243791Sdim    unsigned Size = Context.getTypeSize(Ty);
259243791Sdim    if (!Context.getTargetInfo()
260243791Sdim          .validateConstraintModifier(Literal->getString(), Piece.getModifier(),
261243791Sdim                                      Size))
262243791Sdim      Diag(Exprs[ConstraintIdx]->getLocStart(),
263243791Sdim           diag::warn_asm_mismatched_size_modifier);
264243791Sdim  }
265243791Sdim
266243791Sdim  // Validate tied input operands for type mismatches.
267243791Sdim  for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
268243791Sdim    TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
269243791Sdim
270243791Sdim    // If this is a tied constraint, verify that the output and input have
271243791Sdim    // either exactly the same type, or that they are int/ptr operands with the
272243791Sdim    // same size (int/long, int*/long, are ok etc).
273243791Sdim    if (!Info.hasTiedOperand()) continue;
274243791Sdim
275243791Sdim    unsigned TiedTo = Info.getTiedOperand();
276243791Sdim    unsigned InputOpNo = i+NumOutputs;
277243791Sdim    Expr *OutputExpr = Exprs[TiedTo];
278243791Sdim    Expr *InputExpr = Exprs[InputOpNo];
279243791Sdim
280243791Sdim    if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent())
281243791Sdim      continue;
282243791Sdim
283243791Sdim    QualType InTy = InputExpr->getType();
284243791Sdim    QualType OutTy = OutputExpr->getType();
285243791Sdim    if (Context.hasSameType(InTy, OutTy))
286243791Sdim      continue;  // All types can be tied to themselves.
287243791Sdim
288243791Sdim    // Decide if the input and output are in the same domain (integer/ptr or
289243791Sdim    // floating point.
290243791Sdim    enum AsmDomain {
291243791Sdim      AD_Int, AD_FP, AD_Other
292243791Sdim    } InputDomain, OutputDomain;
293243791Sdim
294243791Sdim    if (InTy->isIntegerType() || InTy->isPointerType())
295243791Sdim      InputDomain = AD_Int;
296243791Sdim    else if (InTy->isRealFloatingType())
297243791Sdim      InputDomain = AD_FP;
298243791Sdim    else
299243791Sdim      InputDomain = AD_Other;
300243791Sdim
301243791Sdim    if (OutTy->isIntegerType() || OutTy->isPointerType())
302243791Sdim      OutputDomain = AD_Int;
303243791Sdim    else if (OutTy->isRealFloatingType())
304243791Sdim      OutputDomain = AD_FP;
305243791Sdim    else
306243791Sdim      OutputDomain = AD_Other;
307243791Sdim
308243791Sdim    // They are ok if they are the same size and in the same domain.  This
309243791Sdim    // allows tying things like:
310243791Sdim    //   void* to int*
311243791Sdim    //   void* to int            if they are the same size.
312243791Sdim    //   double to long double   if they are the same size.
313243791Sdim    //
314243791Sdim    uint64_t OutSize = Context.getTypeSize(OutTy);
315243791Sdim    uint64_t InSize = Context.getTypeSize(InTy);
316243791Sdim    if (OutSize == InSize && InputDomain == OutputDomain &&
317243791Sdim        InputDomain != AD_Other)
318243791Sdim      continue;
319243791Sdim
320243791Sdim    // If the smaller input/output operand is not mentioned in the asm string,
321243791Sdim    // then we can promote the smaller one to a larger input and the asm string
322243791Sdim    // won't notice.
323243791Sdim    bool SmallerValueMentioned = false;
324243791Sdim
325243791Sdim    // If this is a reference to the input and if the input was the smaller
326243791Sdim    // one, then we have to reject this asm.
327243791Sdim    if (isOperandMentioned(InputOpNo, Pieces)) {
328243791Sdim      // This is a use in the asm string of the smaller operand.  Since we
329243791Sdim      // codegen this by promoting to a wider value, the asm will get printed
330243791Sdim      // "wrong".
331243791Sdim      SmallerValueMentioned |= InSize < OutSize;
332243791Sdim    }
333243791Sdim    if (isOperandMentioned(TiedTo, Pieces)) {
334243791Sdim      // If this is a reference to the output, and if the output is the larger
335243791Sdim      // value, then it's ok because we'll promote the input to the larger type.
336243791Sdim      SmallerValueMentioned |= OutSize < InSize;
337243791Sdim    }
338243791Sdim
339243791Sdim    // If the smaller value wasn't mentioned in the asm string, and if the
340243791Sdim    // output was a register, just extend the shorter one to the size of the
341243791Sdim    // larger one.
342243791Sdim    if (!SmallerValueMentioned && InputDomain != AD_Other &&
343243791Sdim        OutputConstraintInfos[TiedTo].allowsRegister())
344243791Sdim      continue;
345243791Sdim
346243791Sdim    // Either both of the operands were mentioned or the smaller one was
347243791Sdim    // mentioned.  One more special case that we'll allow: if the tied input is
348243791Sdim    // integer, unmentioned, and is a constant, then we'll allow truncating it
349243791Sdim    // down to the size of the destination.
350243791Sdim    if (InputDomain == AD_Int && OutputDomain == AD_Int &&
351243791Sdim        !isOperandMentioned(InputOpNo, Pieces) &&
352243791Sdim        InputExpr->isEvaluatable(Context)) {
353243791Sdim      CastKind castKind =
354243791Sdim        (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
355243791Sdim      InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take();
356243791Sdim      Exprs[InputOpNo] = InputExpr;
357243791Sdim      NS->setInputExpr(i, InputExpr);
358243791Sdim      continue;
359243791Sdim    }
360243791Sdim
361243791Sdim    Diag(InputExpr->getLocStart(),
362243791Sdim         diag::err_asm_tying_incompatible_types)
363243791Sdim      << InTy << OutTy << OutputExpr->getSourceRange()
364243791Sdim      << InputExpr->getSourceRange();
365243791Sdim    return StmtError();
366243791Sdim  }
367243791Sdim
368243791Sdim  return Owned(NS);
369243791Sdim}
370243791Sdim
371252723SdimExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
372252723Sdim                                           SourceLocation TemplateKWLoc,
373252723Sdim                                           UnqualifiedId &Id,
374252723Sdim                                           InlineAsmIdentifierInfo &Info,
375252723Sdim                                           bool IsUnevaluatedContext) {
376252723Sdim  Info.clear();
377243791Sdim
378252723Sdim  if (IsUnevaluatedContext)
379252723Sdim    PushExpressionEvaluationContext(UnevaluatedAbstract,
380252723Sdim                                    ReuseLambdaContextDecl);
381243791Sdim
382252723Sdim  ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
383252723Sdim                                        /*trailing lparen*/ false,
384263509Sdim                                        /*is & operand*/ false,
385263509Sdim                                        /*CorrectionCandidateCallback=*/0,
386263509Sdim                                        /*IsInlineAsmIdentifier=*/ true);
387243791Sdim
388252723Sdim  if (IsUnevaluatedContext)
389252723Sdim    PopExpressionEvaluationContext();
390243791Sdim
391252723Sdim  if (!Result.isUsable()) return Result;
392243791Sdim
393252723Sdim  Result = CheckPlaceholderExpr(Result.take());
394252723Sdim  if (!Result.isUsable()) return Result;
395243791Sdim
396252723Sdim  QualType T = Result.get()->getType();
397243791Sdim
398252723Sdim  // For now, reject dependent types.
399252723Sdim  if (T->isDependentType()) {
400252723Sdim    Diag(Id.getLocStart(), diag::err_asm_incomplete_type) << T;
401252723Sdim    return ExprError();
402243791Sdim  }
403243791Sdim
404252723Sdim  // Any sort of function type is fine.
405252723Sdim  if (T->isFunctionType()) {
406252723Sdim    return Result;
407243791Sdim  }
408243791Sdim
409252723Sdim  // Otherwise, it needs to be a complete type.
410252723Sdim  if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) {
411252723Sdim    return ExprError();
412243791Sdim  }
413243791Sdim
414252723Sdim  // Compute the type size (and array length if applicable?).
415252723Sdim  Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity();
416252723Sdim  if (T->isArrayType()) {
417252723Sdim    const ArrayType *ATy = Context.getAsArrayType(T);
418252723Sdim    Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
419252723Sdim    Info.Length = Info.Size / Info.Type;
420243791Sdim  }
421243791Sdim
422252723Sdim  // We can work with the expression as long as it's not an r-value.
423252723Sdim  if (!Result.get()->isRValue())
424252723Sdim    Info.IsVarDecl = true;
425243791Sdim
426252723Sdim  return Result;
427243791Sdim}
428243791Sdim
429243791Sdimbool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
430243791Sdim                                unsigned &Offset, SourceLocation AsmLoc) {
431243791Sdim  Offset = 0;
432243791Sdim  LookupResult BaseResult(*this, &Context.Idents.get(Base), SourceLocation(),
433243791Sdim                          LookupOrdinaryName);
434243791Sdim
435243791Sdim  if (!LookupName(BaseResult, getCurScope()))
436243791Sdim    return true;
437243791Sdim
438243791Sdim  if (!BaseResult.isSingleResult())
439243791Sdim    return true;
440243791Sdim
441252723Sdim  const RecordType *RT = 0;
442243791Sdim  NamedDecl *FoundDecl = BaseResult.getFoundDecl();
443252723Sdim  if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
444243791Sdim    RT = VD->getType()->getAs<RecordType>();
445252723Sdim  else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(FoundDecl))
446243791Sdim    RT = TD->getUnderlyingType()->getAs<RecordType>();
447243791Sdim  if (!RT)
448243791Sdim    return true;
449243791Sdim
450243791Sdim  if (RequireCompleteType(AsmLoc, QualType(RT, 0), 0))
451243791Sdim    return true;
452243791Sdim
453243791Sdim  LookupResult FieldResult(*this, &Context.Idents.get(Member), SourceLocation(),
454243791Sdim                           LookupMemberName);
455243791Sdim
456243791Sdim  if (!LookupQualifiedName(FieldResult, RT->getDecl()))
457243791Sdim    return true;
458243791Sdim
459243791Sdim  // FIXME: Handle IndirectFieldDecl?
460243791Sdim  FieldDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl());
461243791Sdim  if (!FD)
462243791Sdim    return true;
463243791Sdim
464243791Sdim  const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl());
465243791Sdim  unsigned i = FD->getFieldIndex();
466243791Sdim  CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i));
467243791Sdim  Offset = (unsigned)Result.getQuantity();
468243791Sdim
469243791Sdim  return false;
470243791Sdim}
471243791Sdim
472243791SdimStmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
473252723Sdim                                ArrayRef<Token> AsmToks,
474252723Sdim                                StringRef AsmString,
475252723Sdim                                unsigned NumOutputs, unsigned NumInputs,
476252723Sdim                                ArrayRef<StringRef> Constraints,
477252723Sdim                                ArrayRef<StringRef> Clobbers,
478252723Sdim                                ArrayRef<Expr*> Exprs,
479252723Sdim                                SourceLocation EndLoc) {
480252723Sdim  bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
481243791Sdim  MSAsmStmt *NS =
482243791Sdim    new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
483243791Sdim                            /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
484252723Sdim                            Constraints, Exprs, AsmString,
485252723Sdim                            Clobbers, EndLoc);
486243791Sdim  return Owned(NS);
487243791Sdim}
488