clang  3.9.0
SemaStmtAsm.cpp
Go to the documentation of this file.
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 
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"
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,
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 /// \brief Returns true if given expression is not compatible with inline
111 /// assembly's memory constraint; false otherwise.
114  bool is_input_expr) {
115  enum {
116  ExprBitfield = 0,
117  ExprVectorElt,
118  ExprGlobalRegVar,
119  ExprSafeType
120  } EType = ExprSafeType;
121 
122  // Bitfields, vector elements and global register variables are not
123  // compatible.
124  if (E->refersToBitField())
125  EType = ExprBitfield;
126  else if (E->refersToVectorElement())
127  EType = ExprVectorElt;
128  else if (E->refersToGlobalRegisterVar())
129  EType = ExprGlobalRegVar;
130 
131  if (EType != ExprSafeType) {
132  S.Diag(E->getLocStart(), diag::err_asm_non_addr_value_in_memory_constraint)
133  << EType << is_input_expr << Info.getConstraintStr()
134  << E->getSourceRange();
135  return true;
136  }
137 
138  return false;
139 }
140 
142  bool IsVolatile, unsigned NumOutputs,
143  unsigned NumInputs, IdentifierInfo **Names,
144  MultiExprArg constraints, MultiExprArg Exprs,
145  Expr *asmString, MultiExprArg clobbers,
146  SourceLocation RParenLoc) {
147  unsigned NumClobbers = clobbers.size();
148  StringLiteral **Constraints =
149  reinterpret_cast<StringLiteral**>(constraints.data());
150  StringLiteral *AsmString = cast<StringLiteral>(asmString);
151  StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data());
152 
153  SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
154 
155  // The parser verifies that there is a string literal here.
156  assert(AsmString->isAscii());
157 
158  // If we're compiling CUDA file and function attributes indicate that it's not
159  // for this compilation side, skip all the checks.
160  if (!DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl())) {
161  GCCAsmStmt *NS = new (Context) GCCAsmStmt(
162  Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names,
163  Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc);
164  return NS;
165  }
166 
167  for (unsigned i = 0; i != NumOutputs; i++) {
168  StringLiteral *Literal = Constraints[i];
169  assert(Literal->isAscii());
170 
171  StringRef OutputName;
172  if (Names[i])
173  OutputName = Names[i]->getName();
174 
175  TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
177  return StmtError(Diag(Literal->getLocStart(),
178  diag::err_asm_invalid_output_constraint)
179  << Info.getConstraintStr());
180 
181  ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
182  if (ER.isInvalid())
183  return StmtError();
184  Exprs[i] = ER.get();
185 
186  // Check that the output exprs are valid lvalues.
187  Expr *OutputExpr = Exprs[i];
188 
189  // Referring to parameters is not allowed in naked functions.
190  if (CheckNakedParmReference(OutputExpr, *this))
191  return StmtError();
192 
193  // Check that the output expression is compatible with memory constraint.
194  if (Info.allowsMemory() &&
195  checkExprMemoryConstraintCompat(*this, OutputExpr, Info, false))
196  return StmtError();
197 
198  OutputConstraintInfos.push_back(Info);
199 
200  // If this is dependent, just continue.
201  if (OutputExpr->isTypeDependent())
202  continue;
203 
205  OutputExpr->isModifiableLvalue(Context, /*Loc=*/nullptr);
206  switch (IsLV) {
207  case Expr::MLV_Valid:
208  // Cool, this is an lvalue.
209  break;
210  case Expr::MLV_ArrayType:
211  // This is OK too.
212  break;
213  case Expr::MLV_LValueCast: {
214  const Expr *LVal = OutputExpr->IgnoreParenNoopCasts(Context);
215  if (!getLangOpts().HeinousExtensions) {
216  Diag(LVal->getLocStart(), diag::err_invalid_asm_cast_lvalue)
217  << OutputExpr->getSourceRange();
218  } else {
219  Diag(LVal->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
220  << OutputExpr->getSourceRange();
221  }
222  // Accept, even if we emitted an error diagnostic.
223  break;
224  }
227  if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
228  diag::err_dereference_incomplete_type))
229  return StmtError();
230  default:
231  return StmtError(Diag(OutputExpr->getLocStart(),
232  diag::err_asm_invalid_lvalue_in_output)
233  << OutputExpr->getSourceRange());
234  }
235 
236  unsigned Size = Context.getTypeSize(OutputExpr->getType());
238  Size))
239  return StmtError(Diag(OutputExpr->getLocStart(),
240  diag::err_asm_invalid_output_size)
241  << Info.getConstraintStr());
242  }
243 
244  SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
245 
246  for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
247  StringLiteral *Literal = Constraints[i];
248  assert(Literal->isAscii());
249 
250  StringRef InputName;
251  if (Names[i])
252  InputName = Names[i]->getName();
253 
254  TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
255  if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos,
256  Info)) {
257  return StmtError(Diag(Literal->getLocStart(),
258  diag::err_asm_invalid_input_constraint)
259  << Info.getConstraintStr());
260  }
261 
262  ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
263  if (ER.isInvalid())
264  return StmtError();
265  Exprs[i] = ER.get();
266 
267  Expr *InputExpr = Exprs[i];
268 
269  // Referring to parameters is not allowed in naked functions.
270  if (CheckNakedParmReference(InputExpr, *this))
271  return StmtError();
272 
273  // Check that the input expression is compatible with memory constraint.
274  if (Info.allowsMemory() &&
275  checkExprMemoryConstraintCompat(*this, InputExpr, Info, true))
276  return StmtError();
277 
278  // Only allow void types for memory constraints.
279  if (Info.allowsMemory() && !Info.allowsRegister()) {
280  if (CheckAsmLValue(InputExpr, *this))
281  return StmtError(Diag(InputExpr->getLocStart(),
282  diag::err_asm_invalid_lvalue_in_input)
283  << Info.getConstraintStr()
284  << InputExpr->getSourceRange());
285  } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
286  if (!InputExpr->isValueDependent()) {
287  llvm::APSInt Result;
288  if (!InputExpr->EvaluateAsInt(Result, Context))
289  return StmtError(
290  Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
291  << Info.getConstraintStr() << InputExpr->getSourceRange());
292  if (!Info.isValidAsmImmediate(Result))
293  return StmtError(Diag(InputExpr->getLocStart(),
294  diag::err_invalid_asm_value_for_constraint)
295  << Result.toString(10) << Info.getConstraintStr()
296  << InputExpr->getSourceRange());
297  }
298 
299  } else {
300  ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
301  if (Result.isInvalid())
302  return StmtError();
303 
304  Exprs[i] = Result.get();
305  }
306 
307  if (Info.allowsRegister()) {
308  if (InputExpr->getType()->isVoidType()) {
309  return StmtError(Diag(InputExpr->getLocStart(),
310  diag::err_asm_invalid_type_in_input)
311  << InputExpr->getType() << Info.getConstraintStr()
312  << InputExpr->getSourceRange());
313  }
314  }
315 
316  InputConstraintInfos.push_back(Info);
317 
318  const Type *Ty = Exprs[i]->getType().getTypePtr();
319  if (Ty->isDependentType())
320  continue;
321 
322  if (!Ty->isVoidType() || !Info.allowsMemory())
323  if (RequireCompleteType(InputExpr->getLocStart(), Exprs[i]->getType(),
324  diag::err_dereference_incomplete_type))
325  return StmtError();
326 
327  unsigned Size = Context.getTypeSize(Ty);
329  Size))
330  return StmtError(Diag(InputExpr->getLocStart(),
331  diag::err_asm_invalid_input_size)
332  << Info.getConstraintStr());
333  }
334 
335  // Check that the clobbers are valid.
336  for (unsigned i = 0; i != NumClobbers; i++) {
337  StringLiteral *Literal = Clobbers[i];
338  assert(Literal->isAscii());
339 
340  StringRef Clobber = Literal->getString();
341 
342  if (!Context.getTargetInfo().isValidClobber(Clobber))
343  return StmtError(Diag(Literal->getLocStart(),
344  diag::err_asm_unknown_register_name) << Clobber);
345  }
346 
347  GCCAsmStmt *NS =
348  new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
349  NumInputs, Names, Constraints, Exprs.data(),
350  AsmString, NumClobbers, Clobbers, RParenLoc);
351  // Validate the asm string, ensuring it makes sense given the operands we
352  // have.
354  unsigned DiagOffs;
355  if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
356  Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
357  << AsmString->getSourceRange();
358  return StmtError();
359  }
360 
361  // Validate constraints and modifiers.
362  for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
363  GCCAsmStmt::AsmStringPiece &Piece = Pieces[i];
364  if (!Piece.isOperand()) continue;
365 
366  // Look for the correct constraint index.
367  unsigned ConstraintIdx = Piece.getOperandNo();
368  unsigned NumOperands = NS->getNumOutputs() + NS->getNumInputs();
369 
370  // Look for the (ConstraintIdx - NumOperands + 1)th constraint with
371  // modifier '+'.
372  if (ConstraintIdx >= NumOperands) {
373  unsigned I = 0, E = NS->getNumOutputs();
374 
375  for (unsigned Cnt = ConstraintIdx - NumOperands; I != E; ++I)
376  if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) {
377  ConstraintIdx = I;
378  break;
379  }
380 
381  assert(I != E && "Invalid operand number should have been caught in "
382  " AnalyzeAsmString");
383  }
384 
385  // Now that we have the right indexes go ahead and check.
386  StringLiteral *Literal = Constraints[ConstraintIdx];
387  const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
388  if (Ty->isDependentType() || Ty->isIncompleteType())
389  continue;
390 
391  unsigned Size = Context.getTypeSize(Ty);
392  std::string SuggestedModifier;
394  Literal->getString(), Piece.getModifier(), Size,
395  SuggestedModifier)) {
396  Diag(Exprs[ConstraintIdx]->getLocStart(),
397  diag::warn_asm_mismatched_size_modifier);
398 
399  if (!SuggestedModifier.empty()) {
400  auto B = Diag(Piece.getRange().getBegin(),
401  diag::note_asm_missing_constraint_modifier)
402  << SuggestedModifier;
403  SuggestedModifier = "%" + SuggestedModifier + Piece.getString();
404  B.AddFixItHint(FixItHint::CreateReplacement(Piece.getRange(),
405  SuggestedModifier));
406  }
407  }
408  }
409 
410  // Validate tied input operands for type mismatches.
411  unsigned NumAlternatives = ~0U;
412  for (unsigned i = 0, e = OutputConstraintInfos.size(); i != e; ++i) {
413  TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
414  StringRef ConstraintStr = Info.getConstraintStr();
415  unsigned AltCount = ConstraintStr.count(',') + 1;
416  if (NumAlternatives == ~0U)
417  NumAlternatives = AltCount;
418  else if (NumAlternatives != AltCount)
419  return StmtError(Diag(NS->getOutputExpr(i)->getLocStart(),
420  diag::err_asm_unexpected_constraint_alternatives)
421  << NumAlternatives << AltCount);
422  }
423  SmallVector<size_t, 4> InputMatchedToOutput(OutputConstraintInfos.size(),
424  ~0U);
425  for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
426  TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
427  StringRef ConstraintStr = Info.getConstraintStr();
428  unsigned AltCount = ConstraintStr.count(',') + 1;
429  if (NumAlternatives == ~0U)
430  NumAlternatives = AltCount;
431  else if (NumAlternatives != AltCount)
432  return StmtError(Diag(NS->getInputExpr(i)->getLocStart(),
433  diag::err_asm_unexpected_constraint_alternatives)
434  << NumAlternatives << AltCount);
435 
436  // If this is a tied constraint, verify that the output and input have
437  // either exactly the same type, or that they are int/ptr operands with the
438  // same size (int/long, int*/long, are ok etc).
439  if (!Info.hasTiedOperand()) continue;
440 
441  unsigned TiedTo = Info.getTiedOperand();
442  unsigned InputOpNo = i+NumOutputs;
443  Expr *OutputExpr = Exprs[TiedTo];
444  Expr *InputExpr = Exprs[InputOpNo];
445 
446  // Make sure no more than one input constraint matches each output.
447  assert(TiedTo < InputMatchedToOutput.size() && "TiedTo value out of range");
448  if (InputMatchedToOutput[TiedTo] != ~0U) {
449  Diag(NS->getInputExpr(i)->getLocStart(),
450  diag::err_asm_input_duplicate_match)
451  << TiedTo;
452  Diag(NS->getInputExpr(InputMatchedToOutput[TiedTo])->getLocStart(),
453  diag::note_asm_input_duplicate_first)
454  << TiedTo;
455  return StmtError();
456  }
457  InputMatchedToOutput[TiedTo] = i;
458 
459  if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent())
460  continue;
461 
462  QualType InTy = InputExpr->getType();
463  QualType OutTy = OutputExpr->getType();
464  if (Context.hasSameType(InTy, OutTy))
465  continue; // All types can be tied to themselves.
466 
467  // Decide if the input and output are in the same domain (integer/ptr or
468  // floating point.
469  enum AsmDomain {
470  AD_Int, AD_FP, AD_Other
471  } InputDomain, OutputDomain;
472 
473  if (InTy->isIntegerType() || InTy->isPointerType())
474  InputDomain = AD_Int;
475  else if (InTy->isRealFloatingType())
476  InputDomain = AD_FP;
477  else
478  InputDomain = AD_Other;
479 
480  if (OutTy->isIntegerType() || OutTy->isPointerType())
481  OutputDomain = AD_Int;
482  else if (OutTy->isRealFloatingType())
483  OutputDomain = AD_FP;
484  else
485  OutputDomain = AD_Other;
486 
487  // They are ok if they are the same size and in the same domain. This
488  // allows tying things like:
489  // void* to int*
490  // void* to int if they are the same size.
491  // double to long double if they are the same size.
492  //
493  uint64_t OutSize = Context.getTypeSize(OutTy);
494  uint64_t InSize = Context.getTypeSize(InTy);
495  if (OutSize == InSize && InputDomain == OutputDomain &&
496  InputDomain != AD_Other)
497  continue;
498 
499  // If the smaller input/output operand is not mentioned in the asm string,
500  // then we can promote the smaller one to a larger input and the asm string
501  // won't notice.
502  bool SmallerValueMentioned = false;
503 
504  // If this is a reference to the input and if the input was the smaller
505  // one, then we have to reject this asm.
506  if (isOperandMentioned(InputOpNo, Pieces)) {
507  // This is a use in the asm string of the smaller operand. Since we
508  // codegen this by promoting to a wider value, the asm will get printed
509  // "wrong".
510  SmallerValueMentioned |= InSize < OutSize;
511  }
512  if (isOperandMentioned(TiedTo, Pieces)) {
513  // If this is a reference to the output, and if the output is the larger
514  // value, then it's ok because we'll promote the input to the larger type.
515  SmallerValueMentioned |= OutSize < InSize;
516  }
517 
518  // If the smaller value wasn't mentioned in the asm string, and if the
519  // output was a register, just extend the shorter one to the size of the
520  // larger one.
521  if (!SmallerValueMentioned && InputDomain != AD_Other &&
522  OutputConstraintInfos[TiedTo].allowsRegister())
523  continue;
524 
525  // Either both of the operands were mentioned or the smaller one was
526  // mentioned. One more special case that we'll allow: if the tied input is
527  // integer, unmentioned, and is a constant, then we'll allow truncating it
528  // down to the size of the destination.
529  if (InputDomain == AD_Int && OutputDomain == AD_Int &&
530  !isOperandMentioned(InputOpNo, Pieces) &&
531  InputExpr->isEvaluatable(Context)) {
532  CastKind castKind =
533  (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
534  InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).get();
535  Exprs[InputOpNo] = InputExpr;
536  NS->setInputExpr(i, InputExpr);
537  continue;
538  }
539 
540  Diag(InputExpr->getLocStart(),
541  diag::err_asm_tying_incompatible_types)
542  << InTy << OutTy << OutputExpr->getSourceRange()
543  << InputExpr->getSourceRange();
544  return StmtError();
545  }
546 
547  return NS;
548 }
549 
551  llvm::InlineAsmIdentifierInfo &Info) {
552  // Compute the type size (and array length if applicable?).
553  Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity();
554  if (T->isArrayType()) {
555  const ArrayType *ATy = Context.getAsArrayType(T);
556  Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
557  Info.Length = Info.Size / Info.Type;
558  }
559 }
560 
562  SourceLocation TemplateKWLoc,
563  UnqualifiedId &Id,
564  llvm::InlineAsmIdentifierInfo &Info,
565  bool IsUnevaluatedContext) {
566  Info.clear();
567 
568  if (IsUnevaluatedContext)
569  PushExpressionEvaluationContext(UnevaluatedAbstract,
570  ReuseLambdaContextDecl);
571 
572  ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
573  /*trailing lparen*/ false,
574  /*is & operand*/ false,
575  /*CorrectionCandidateCallback=*/nullptr,
576  /*IsInlineAsmIdentifier=*/ true);
577 
578  if (IsUnevaluatedContext)
579  PopExpressionEvaluationContext();
580 
581  if (!Result.isUsable()) return Result;
582 
583  Result = CheckPlaceholderExpr(Result.get());
584  if (!Result.isUsable()) return Result;
585 
586  // Referring to parameters is not allowed in naked functions.
587  if (CheckNakedParmReference(Result.get(), *this))
588  return ExprError();
589 
590  QualType T = Result.get()->getType();
591 
592  if (T->isDependentType()) {
593  return Result;
594  }
595 
596  // Any sort of function type is fine.
597  if (T->isFunctionType()) {
598  return Result;
599  }
600 
601  // Otherwise, it needs to be a complete type.
602  if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) {
603  return ExprError();
604  }
605 
606  fillInlineAsmTypeInfo(Context, T, Info);
607 
608  // We can work with the expression as long as it's not an r-value.
609  if (!Result.get()->isRValue())
610  Info.IsVarDecl = true;
611 
612  return Result;
613 }
614 
615 bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
616  unsigned &Offset, SourceLocation AsmLoc) {
617  Offset = 0;
619  Member.split(Members, ".");
620 
622  LookupOrdinaryName);
623 
624  if (!LookupName(BaseResult, getCurScope()))
625  return true;
626 
627  if(!BaseResult.isSingleResult())
628  return true;
629  NamedDecl *FoundDecl = BaseResult.getFoundDecl();
630  for (StringRef NextMember : Members) {
631  const RecordType *RT = nullptr;
632  if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
633  RT = VD->getType()->getAs<RecordType>();
634  else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl)) {
635  MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
636  RT = TD->getUnderlyingType()->getAs<RecordType>();
637  } else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
638  RT = TD->getTypeForDecl()->getAs<RecordType>();
639  else if (FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl))
640  RT = TD->getType()->getAs<RecordType>();
641  if (!RT)
642  return true;
643 
644  if (RequireCompleteType(AsmLoc, QualType(RT, 0),
645  diag::err_asm_incomplete_type))
646  return true;
647 
648  LookupResult FieldResult(*this, &Context.Idents.get(NextMember),
649  SourceLocation(), LookupMemberName);
650 
651  if (!LookupQualifiedName(FieldResult, RT->getDecl()))
652  return true;
653 
654  if (!FieldResult.isSingleResult())
655  return true;
656  FoundDecl = FieldResult.getFoundDecl();
657 
658  // FIXME: Handle IndirectFieldDecl?
659  FieldDecl *FD = dyn_cast<FieldDecl>(FoundDecl);
660  if (!FD)
661  return true;
662 
664  unsigned i = FD->getFieldIndex();
666  Offset += (unsigned)Result.getQuantity();
667  }
668 
669  return false;
670 }
671 
674  llvm::InlineAsmIdentifierInfo &Info,
675  SourceLocation AsmLoc) {
676  Info.clear();
677 
678  QualType T = E->getType();
679  if (T->isDependentType()) {
680  DeclarationNameInfo NameInfo;
681  NameInfo.setLoc(AsmLoc);
682  NameInfo.setName(&Context.Idents.get(Member));
684  Context, E, T, /*IsArrow=*/false, AsmLoc, NestedNameSpecifierLoc(),
685  SourceLocation(),
686  /*FirstQualifierInScope=*/nullptr, NameInfo, /*TemplateArgs=*/nullptr);
687  }
688 
689  const RecordType *RT = T->getAs<RecordType>();
690  // FIXME: Diagnose this as field access into a scalar type.
691  if (!RT)
692  return ExprResult();
693 
694  LookupResult FieldResult(*this, &Context.Idents.get(Member), AsmLoc,
695  LookupMemberName);
696 
697  if (!LookupQualifiedName(FieldResult, RT->getDecl()))
698  return ExprResult();
699 
700  // Only normal and indirect field results will work.
701  ValueDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl());
702  if (!FD)
703  FD = dyn_cast<IndirectFieldDecl>(FieldResult.getFoundDecl());
704  if (!FD)
705  return ExprResult();
706 
707  // Make an Expr to thread through OpDecl.
708  ExprResult Result = BuildMemberReferenceExpr(
709  E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(),
710  SourceLocation(), nullptr, FieldResult, nullptr, nullptr);
711  if (Result.isInvalid())
712  return Result;
713  Info.OpDecl = Result.get();
714 
715  fillInlineAsmTypeInfo(Context, Result.get()->getType(), Info);
716 
717  // Fields are "variables" as far as inline assembly is concerned.
718  Info.IsVarDecl = true;
719 
720  return Result;
721 }
722 
724  ArrayRef<Token> AsmToks,
725  StringRef AsmString,
726  unsigned NumOutputs, unsigned NumInputs,
727  ArrayRef<StringRef> Constraints,
728  ArrayRef<StringRef> Clobbers,
729  ArrayRef<Expr*> Exprs,
730  SourceLocation EndLoc) {
731  bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
732  getCurFunction()->setHasBranchProtectedScope();
733  MSAsmStmt *NS =
734  new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
735  /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
736  Constraints, Exprs, AsmString,
737  Clobbers, EndLoc);
738  return NS;
739 }
740 
741 LabelDecl *Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
742  SourceLocation Location,
743  bool AlwaysCreate) {
744  LabelDecl* Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
745  Location);
746 
747  if (Label->isMSAsmLabel()) {
748  // If we have previously created this label implicitly, mark it as used.
749  Label->markUsed(Context);
750  } else {
751  // Otherwise, insert it, but only resolve it if we have seen the label itself.
752  std::string InternalName;
753  llvm::raw_string_ostream OS(InternalName);
754  // Create an internal name for the label. The name should not be a valid mangled
755  // name, and should be unique. We use a dot to make the name an invalid mangled
756  // name.
757  OS << "__MSASMLABEL_." << MSAsmLabelNameCounter++ << "__";
758  for (auto it = ExternalLabelName.begin(); it != ExternalLabelName.end();
759  ++it) {
760  OS << *it;
761  if (*it == '$') {
762  // We escape '$' in asm strings by replacing it with "$$"
763  OS << '$';
764  }
765  }
766  Label->setMSAsmLabel(OS.str());
767  }
768  if (AlwaysCreate) {
769  // The label might have been created implicitly from a previously encountered
770  // goto statement. So, for both newly created and looked up labels, we mark
771  // them as resolved.
772  Label->setMSAsmLabelResolved();
773  }
774  // Adjust their location for being able to generate accurate diagnostics.
775  Label->setLocation(Location);
776 
777  return Label;
778 }
This represents a GCC inline-assembly statement extension.
Definition: Stmt.h:1565
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Definition: Decl.h:1561
unsigned getNumOutputs() const
Definition: Stmt.h:1462
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
A (possibly-)qualified type.
Definition: Type.h:598
bool isInvalid() const
Definition: Ownership.h:160
SourceLocation getBegin() const
static CXXDependentScopeMemberExpr * Create(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs)
Definition: ExprCXX.cpp:1143
const LangOptions & getLangOpts() const
Definition: Sema.h:1062
StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, IdentifierInfo **Names, MultiExprArg Constraints, MultiExprArg Exprs, Expr *AsmString, MultiExprArg Clobbers, SourceLocation RParenLoc)
ActionResult< Expr * > ExprResult
Definition: Ownership.h:253
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition: CharUnits.h:179
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition: Sema.h:1139
PtrTy get() const
Definition: Ownership.h:164
The base class of the type hierarchy.
Definition: Type.h:1281
bool validateOutputConstraint(ConstraintInfo &Info) const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:2456
bool validateInputConstraint(MutableArrayRef< ConstraintInfo > OutputConstraints, ConstraintInfo &info) const
bool isBooleanType() const
Definition: Type.h:5743
SourceLocation getLocStart() const LLVM_READONLY
Definition: Expr.h:1602
isModifiableLvalueResult
Definition: Expr.h:267
void setInputExpr(unsigned i, Expr *E)
Definition: Stmt.cpp:411
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Definition: Decl.h:768
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:1813
virtual bool validateConstraintModifier(StringRef, char, unsigned, std::string &) const
Defines the clang::Expr interface and subclasses for C++ expressions.
static void fillInlineAsmTypeInfo(const ASTContext &Context, QualType T, llvm::InlineAsmIdentifierInfo &Info)
bool isVoidType() const
Definition: Type.h:5680
static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E, TargetInfo::ConstraintInfo &Info, bool is_input_expr)
Returns true if given expression is not compatible with inline assembly's memory constraint; false ot...
bool refersToGlobalRegisterVar() const
Returns whether this expression refers to a global register variable.
Definition: Expr.cpp:3350
One of these records is kept for each identifier that is lexed.
unsigned getNumInputs() const
Definition: Stmt.h:1484
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:92
A C++ nested-name-specifier augmented with source location information.
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
Definition: Decl.h:2293
void setName(DeclarationName N)
setName - Sets the embedded declaration name.
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:1982
virtual bool validateOutputSize(StringRef, unsigned) const
bool refersToVectorElement() const
Returns whether this expression refers to a vector element.
Definition: Expr.cpp:3330
static bool isOperandMentioned(unsigned OpNo, ArrayRef< GCCAsmStmt::AsmStringPiece > AsmStrPieces)
isOperandMentioned - Return true if the specified operand # is mentioned anywhere in the decomposed a...
Definition: SemaStmtAsm.cpp:65
IdentifierTable & Idents
Definition: ASTContext.h:459
LabelDecl * GetOrCreateMSAsmLabel(StringRef ExternalLabelName, SourceLocation Location, bool AlwaysCreate)
virtual bool validateInputSize(StringRef, unsigned) const
Type(TypeClass tc, QualType canon, bool Dependent, bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack)
Definition: Type.h:1502
Represents a C++ unqualified-id that has been parsed.
Definition: DeclSpec.h:884
Represents the results of name lookup.
Definition: Sema/Lookup.h:30
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:588
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
uint32_t Offset
Definition: CacheTokens.cpp:44
static bool CheckAsmLValue(const Expr *E, Sema &S)
CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently ignore "noop" casts in p...
Definition: SemaStmtAsm.cpp:37
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
StmtResult StmtError()
Definition: Ownership.h:269
TypeDecl - Represents a declaration of a type.
Definition: Decl.h:2569
bool isValueDependent() const
isValueDependent - Determines whether this expression is value-dependent (C++ [temp.dep.constexpr]).
Definition: Expr.h:147
Expr * getOutputExpr(unsigned i)
Definition: Stmt.cpp:397
RecordDecl * getDecl() const
Definition: Type.h:3716
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
Definition: RecordLayout.h:177
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:63
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types...
Definition: Type.cpp:1892
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
detail::InMemoryDirectory::const_iterator I
ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member, llvm::InlineAsmIdentifierInfo &Info, SourceLocation AsmLoc)
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:263
Expr * IgnoreParenNoopCasts(ASTContext &Ctx) LLVM_READONLY
IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the value (including ptr->int ...
Definition: Expr.cpp:2446
CastKind
CastKind - The kind of operation required for a conversion.
ASTContext * Context
ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, llvm::InlineAsmIdentifierInfo &Info, bool IsUnevaluatedContext)
static bool CheckNakedParmReference(Expr *E, Sema &S)
Definition: SemaStmtAsm.cpp:79
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:1799
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
Definition: RecordLayout.h:34
ValueDecl - Represent the declaration of a variable (in which case it is an lvalue) a function (in wh...
Definition: Decl.h:590
Expr - This represents one expression.
Definition: Expr.h:105
StringRef getName() const
Return the actual identifier string.
AsmStringPiece - this is part of a decomposed asm string specification (for use with the AnalyzeAsmSt...
Definition: Stmt.h:1599
bool isValidClobber(StringRef Name) const
Returns whether the passed in string is a valid clobber in an inline asm statement.
Defines the clang::Preprocessor interface.
bool isMSAsmLabel() const
Definition: Decl.h:459
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, does not have an incomplet...
Defines the clang::TypeLoc interface and its subclasses.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:1774
bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer...
This represents a Microsoft inline-assembly statement extension.
Definition: Stmt.h:1744
The result type of a method or function.
ActionResult - This structure is used while parsing/acting on expressions, stmts, etc...
Definition: Ownership.h:146
Encodes a location in the source.
char getModifier() const
getModifier - Get the modifier for this operand, if present.
Definition: Stmt.cpp:388
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
LabelDecl - Represents the declaration of a label.
Definition: Decl.h:424
CharSourceRange getRange() const
Definition: Stmt.h:1632
bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset, SourceLocation AsmLoc)
bool isRValue() const
Definition: Expr.h:248
Expr * getInputExpr(unsigned i)
Definition: Stmt.cpp:408
bool isTypeDependent() const
isTypeDependent - Determines whether this expression is type-dependent (C++ [temp.dep.expr]), which means that its type could change from one template instantiation to the next.
Definition: Expr.h:165
bool isAscii() const
Definition: Expr.h:1557
ActionResult< CXXBaseSpecifier * > BaseResult
Definition: Ownership.h:256
bool refersToBitField() const
Returns true if this expression is a gl-value that potentially refers to a bit-field.
Definition: Expr.h:433
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:2609
QualType getType() const
Definition: Expr.h:126
unsigned AnalyzeAsmString(SmallVectorImpl< AsmStringPiece > &Pieces, const ASTContext &C, unsigned &DiagOffs) const
AnalyzeAsmString - Analyze the asm string of the current asm, decomposing it into pieces...
Definition: Stmt.cpp:475
IndirectFieldDecl - An instance of this class is created to represent a field injected from an anonym...
Definition: Decl.h:2521
bool hasTiedOperand() const
Return true if this input operand is a matching constraint that ties it to an output operand...
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language...
Definition: Expr.h:247
StringRef getString() const
Definition: Expr.h:1514
detail::InMemoryDirectory::const_iterator E
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
bool DeclAttrsMatchCUDAMode(const LangOptions &LangOpts, Decl *D)
Definition: SemaInternal.h:54
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:3707
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:5818
bool isFunctionType() const
Definition: Type.h:5479
unsigned getOperandNo() const
Definition: Stmt.h:1627
unsigned getFieldIndex() const
getFieldIndex - Returns the index of this field within its record, as appropriate for passing to ASTR...
Definition: Decl.cpp:3474
bool isUsable() const
Definition: Ownership.h:161
void setLoc(SourceLocation L)
setLoc - Sets the main location of the declaration name.
const std::string & getString() const
Definition: Stmt.h:1623
void setMSAsmLabel(StringRef Name)
Definition: Decl.cpp:3997
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:311
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string...
Definition: Diagnostic.h:115
bool isArrayType() const
Definition: Type.h:5521
StringLiteral - This represents a string literal expression, e.g.
Definition: Expr.h:1466
Defines the clang::TargetInfo interface.
ExprResult ExprError()
Definition: Ownership.h:268
StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, ArrayRef< Token > AsmToks, StringRef AsmString, unsigned NumOutputs, unsigned NumInputs, ArrayRef< StringRef > Constraints, ArrayRef< StringRef > Clobbers, ArrayRef< Expr * > Exprs, SourceLocation EndLoc)
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:932
QualType getElementType() const
Definition: Type.h:2490
void setMSAsmLabelResolved()
Definition: Decl.h:463
ASTContext & Context
Definition: Sema.h:299
NamedDecl - This represents a decl with a name.
Definition: Decl.h:213
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:5702
bool isPointerType() const
Definition: Type.h:5482