ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, llvm::InlineAsmIdentifierInfo &Info, bool IsUnevaluatedContext) { Info.clear(); if (IsUnevaluatedContext) PushExpressionEvaluationContext(UnevaluatedAbstract, ReuseLambdaContextDecl); ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id, /*trailing lparen*/ false, /*is & operand*/ false, /*CorrectionCandidateCallback=*/nullptr, /*IsInlineAsmIdentifier=*/ true); if (IsUnevaluatedContext) PopExpressionEvaluationContext(); if (!Result.isUsable()) return Result; Result = CheckPlaceholderExpr(Result.get()); if (!Result.isUsable()) return Result; QualType T = Result.get()->getType(); // For now, reject dependent types. if (T->isDependentType()) { Diag(Id.getLocStart(), diag::err_asm_incomplete_type) << T; return ExprError(); } // Any sort of function type is fine. if (T->isFunctionType()) { return Result; } // Otherwise, it needs to be a complete type. if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) { return ExprError(); } // Compute the type size (and array length if applicable?). Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity(); if (T->isArrayType()) { const ArrayType *ATy = Context.getAsArrayType(T); Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity(); Info.Length = Info.Size / Info.Type; } // We can work with the expression as long as it's not an r-value. if (!Result.get()->isRValue()) Info.IsVarDecl = true; return Result; }
ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, llvm::InlineAsmIdentifierInfo &Info, bool IsUnevaluatedContext) { Info.clear(); if (IsUnevaluatedContext) PushExpressionEvaluationContext(UnevaluatedAbstract, ReuseLambdaContextDecl); ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id, /*trailing lparen*/ false, /*is & operand*/ false, /*CorrectionCandidateCallback=*/nullptr, /*IsInlineAsmIdentifier=*/ true); if (IsUnevaluatedContext) PopExpressionEvaluationContext(); if (!Result.isUsable()) return Result; Result = CheckPlaceholderExpr(Result.get()); if (!Result.isUsable()) return Result; // Referring to parameters is not allowed in naked functions. if (CheckNakedParmReference(Result.get(), *this)) return ExprError(); QualType T = Result.get()->getType(); // For now, reject dependent types. if (T->isDependentType()) { Diag(Id.getLocStart(), diag::err_asm_incomplete_type) << T; return ExprError(); } // Any sort of function type is fine. if (T->isFunctionType()) { return Result; } // Otherwise, it needs to be a complete type. if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) { return ExprError(); } fillInlineAsmTypeInfo(Context, T, Info); // We can work with the expression as long as it's not an r-value. if (!Result.get()->isRValue()) Info.IsVarDecl = true; return Result; }
ExprResult Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member, llvm::InlineAsmIdentifierInfo &Info, SourceLocation AsmLoc) { Info.clear(); QualType T = E->getType(); if (T->isDependentType()) { DeclarationNameInfo NameInfo; NameInfo.setLoc(AsmLoc); NameInfo.setName(&Context.Idents.get(Member)); return CXXDependentScopeMemberExpr::Create( Context, E, T, /*IsArrow=*/false, AsmLoc, NestedNameSpecifierLoc(), SourceLocation(), /*FirstQualifierInScope=*/nullptr, NameInfo, /*TemplateArgs=*/nullptr); } const RecordType *RT = T->getAs<RecordType>(); // FIXME: Diagnose this as field access into a scalar type. if (!RT) return ExprResult(); LookupResult FieldResult(*this, &Context.Idents.get(Member), AsmLoc, LookupMemberName); if (!LookupQualifiedName(FieldResult, RT->getDecl())) return ExprResult(); // Only normal and indirect field results will work. ValueDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl()); if (!FD) FD = dyn_cast<IndirectFieldDecl>(FieldResult.getFoundDecl()); if (!FD) return ExprResult(); // Make an Expr to thread through OpDecl. ExprResult Result = BuildMemberReferenceExpr( E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(), SourceLocation(), nullptr, FieldResult, nullptr, nullptr); if (Result.isInvalid()) return Result; Info.OpDecl = Result.get(); fillInlineAsmTypeInfo(Context, Result.get()->getType(), Info); // Fields are "variables" as far as inline assembly is concerned. Info.IsVarDecl = true; return Result; }
ExprResult Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member, unsigned &Offset, llvm::InlineAsmIdentifierInfo &Info, SourceLocation AsmLoc) { Info.clear(); const RecordType *RT = E->getType()->getAs<RecordType>(); // FIXME: Diagnose this as field access into a scalar type. if (!RT) return ExprResult(); LookupResult FieldResult(*this, &Context.Idents.get(Member), AsmLoc, LookupMemberName); if (!LookupQualifiedName(FieldResult, RT->getDecl())) return ExprResult(); // Only normal and indirect field results will work. ValueDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl()); if (!FD) FD = dyn_cast<IndirectFieldDecl>(FieldResult.getFoundDecl()); if (!FD) return ExprResult(); Offset = (unsigned)Context.toCharUnitsFromBits(Context.getFieldOffset(FD)) .getQuantity(); // Make an Expr to thread through OpDecl. ExprResult Result = BuildMemberReferenceExpr( E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(), SourceLocation(), nullptr, FieldResult, nullptr, nullptr); if (Result.isInvalid()) return Result; Info.OpDecl = Result.get(); fillInlineAsmTypeInfo(Context, Result.get()->getType(), Info); // Fields are "variables" as far as inline assembly is concerned. Info.IsVarDecl = true; return Result; }