[PATCH] D13285: Fix for bug 24196: clang fails on assertion on complex doubles multiplication when EH is enabled
d.zobnin.bugzilla created this revision. d.zobnin.bugzilla added reviewers: rsmith, rjmccall. d.zobnin.bugzilla added a subscriber: cfe-commits. This patch fixes an assertion failure, caused by EmitCall function producing llvm::InvokeInst* when llvm::CallInst* is needed (when multiplication of complex arguments is being emitted). http://reviews.llvm.org/D13285 Files: lib/CodeGen/CGCall.cpp lib/CodeGen/CGExprComplex.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenCXX/complex_mul_call.cpp Index: lib/CodeGen/CGExprComplex.cpp === --- lib/CodeGen/CGExprComplex.cpp +++ lib/CodeGen/CGExprComplex.cpp @@ -592,7 +592,7 @@ llvm::Instruction *Call; RValue Res = CGF.EmitCall(FuncInfo, Func, ReturnValueSlot(), Args, -nullptr, &Call); +nullptr, &Call, /*forceCallInstCreation =*/ true); cast(Call)->setCallingConv(CGF.CGM.getBuiltinCC()); cast(Call)->setDoesNotThrow(); Index: lib/CodeGen/CGCall.cpp === --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -3102,9 +3102,17 @@ ReturnValueSlot ReturnValue, const CallArgList &CallArgs, const Decl *TargetDecl, - llvm::Instruction **callOrInvoke) { + llvm::Instruction **callOrInvoke, + bool forceCallInstCreation) { // FIXME: We no longer need the types from CallArgs; lift up and simplify. + // It may be nessesary to create a CallInst* even if TargetDecl is not given + // (e. g. when emitting a complex operation call). Without TargetDecl there is + // no way to check the NoUnwind attribute required for CallInst creation. Use + // specific flag then, but take care of possible logical violations. + assert(!(TargetDecl && forceCallInstCreation) && + "Should not force creation of CallInst if TargetDecl is present!"); + // Handle struct-return functions by passing a pointer to the // location that we would like to return into. QualType RetTy = CallInfo.getReturnType(); @@ -3442,7 +3450,7 @@ InvokeDest = getInvokeDest(); llvm::CallSite CS; - if (!InvokeDest) { + if (!InvokeDest || forceCallInstCreation) { CS = Builder.CreateCall(Callee, IRCallArgs); } else { llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); Index: lib/CodeGen/CodeGenFunction.h === --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -2651,7 +2651,8 @@ ReturnValueSlot ReturnValue, const CallArgList &Args, const Decl *TargetDecl = nullptr, - llvm::Instruction **callOrInvoke = nullptr); + llvm::Instruction **callOrInvoke = nullptr, + bool forceCallInstCreation = false); RValue EmitCall(QualType FnType, llvm::Value *Callee, const CallExpr *E, ReturnValueSlot ReturnValue, Index: test/CodeGenCXX/complex_mul_call.cpp === --- test/CodeGenCXX/complex_mul_call.cpp +++ test/CodeGenCXX/complex_mul_call.cpp @@ -0,0 +1,24 @@ +// Check that multiplication of complex arguments is performed properly without +// assersion fails when exceptions are enabled. +// +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-llvm %s -o - | FileCheck %s + +struct A { + int x; + A() { x = 10; } + ~A() { x = 20; } +}; + +int main() { + { +A a; +double __complex__ d; +float __complex__ f; +// CHECK-LABEL: main +// CHECK-DAG: call {{.*}} @__muldc3 +double __complex__ d1 = d * d; +// CHECK-DAG: call {{.*}} @__mulsc3 +float __complex__ f1 = f * f; + } + return 0; +} Index: lib/CodeGen/CGExprComplex.cpp === --- lib/CodeGen/CGExprComplex.cpp +++ lib/CodeGen/CGExprComplex.cpp @@ -592,7 +592,7 @@ llvm::Instruction *Call; RValue Res = CGF.EmitCall(FuncInfo, Func, ReturnValueSlot(), Args, -nullptr, &Call); +nullptr, &Call, /*forceCallInstCreation =*/ true); cast(Call)->setCallingConv(CGF.CGM.getBuiltinCC()); cast(Call)->setDoesNotThrow(); Index: lib/CodeGen/CGCall.cpp === --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -3102,9 +3102,17 @@ ReturnValueSlot ReturnValue, const CallArgList &CallArgs, const Decl *TargetDecl, - llvm::Instruction **callOrInvoke) { + llvm::Instruction **call
[PATCH] D14467: [MS] Fix for bug 25013 - #pragma vtordisp is unknown inside functions.
d.zobnin.bugzilla created this revision. d.zobnin.bugzilla added a reviewer: rnk. d.zobnin.bugzilla added a subscriber: cfe-commits. This patch adds support of #pragma vtordisp inside functions in attempt to improve compatibility. Microsoft compiler appears to save the stack of vtordisp modes on entry of struct methods' bodies and restore it on exit (method-local vtordisp). http://reviews.llvm.org/D14467 Files: include/clang/Sema/Sema.h lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseStmt.cpp test/Layout/ms-vtordisp-local.cpp test/SemaCXX/pragma-vtordisp.cpp Index: lib/Parse/ParseDeclCXX.cpp === --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -2854,6 +2854,11 @@ return DeclGroupPtrTy(); } + if (Tok.is(tok::annot_pragma_ms_vtordisp)) { +HandlePragmaMSVtorDisp(); +return DeclGroupPtrTy(); + } + // If we see a namespace here, a close brace was missing somewhere. if (Tok.is(tok::kw_namespace)) { DiagnoseUnexpectedNamespace(cast(TagDecl)); Index: lib/Parse/ParseStmt.cpp === --- lib/Parse/ParseStmt.cpp +++ lib/Parse/ParseStmt.cpp @@ -358,6 +358,11 @@ HandlePragmaMSPragma(); return StmtEmpty(); + case tok::annot_pragma_ms_vtordisp: +ProhibitAttributes(Attrs); +HandlePragmaMSVtorDisp(); +return StmtEmpty(); + case tok::annot_pragma_loop_hint: ProhibitAttributes(Attrs); return ParsePragmaLoopHint(Stmts, OnlyStatement, TrailingElseLoc, Attrs); @@ -885,6 +890,9 @@ case tok::annot_pragma_ms_pragma: HandlePragmaMSPragma(); break; +case tok::annot_pragma_ms_vtordisp: + HandlePragmaMSVtorDisp(); + break; default: checkForPragmas = false; break; @@ -1895,6 +1903,11 @@ PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc, "parsing function body"); + // Save and reset current vtordisp stack if we have entered a C++ method body. + bool IsCXXMethod = + getLangOpts().CPlusPlus && Decl && isa(Decl); + Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod); + // Do not enter a scope for the brace, as the arguments are in the same scope // (the function body) as the body itself. Instead, just read the statement // list and put it into a CompoundStmt for safe keeping. @@ -1934,6 +1947,11 @@ return Actions.ActOnSkippedFunctionBody(Decl); } + // Save and reset current vtordisp stack if we have entered a C++ method body. + bool IsCXXMethod = + getLangOpts().CPlusPlus && Decl && isa(Decl); + Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod); + SourceLocation LBraceLoc = Tok.getLocation(); StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc, /*FnTry*/true)); // If we failed to parse the try-catch, we just give the function an empty Index: include/clang/Sema/Sema.h === --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -1008,6 +1008,24 @@ bool OldFPContractState : 1; }; + /// Records and restores the vtordisp state on entry/exit of C++ method body. + class VtorDispStackRAII { + public: +VtorDispStackRAII(Sema &S, bool ShouldSaveAndRestore) + : S(S), ShouldSaveAndRestore(ShouldSaveAndRestore), OldVtorDispStack() { + if (ShouldSaveAndRestore) +OldVtorDispStack = S.VtorDispModeStack; +} +~VtorDispStackRAII() { + if (ShouldSaveAndRestore) +S.VtorDispModeStack = OldVtorDispStack; +} + private: +Sema &S; +bool ShouldSaveAndRestore; +SmallVector OldVtorDispStack; + }; + void addImplicitTypedef(StringRef Name, QualType T); public: Index: test/Layout/ms-vtordisp-local.cpp === --- test/Layout/ms-vtordisp-local.cpp +++ test/Layout/ms-vtordisp-local.cpp @@ -0,0 +1,194 @@ +// RUN: %clang_cc1 -fms-extensions -fexceptions -fcxx-exceptions -emit-llvm-only -triple x86_64-pc-win32 -fdump-record-layouts -fsyntax-only %s 2>&1 | FileCheck %s + +struct Base { + virtual ~Base() {} + virtual void BaseFunc() {} +}; + +#pragma vtordisp(0) + +struct Container { + static void f() try { +#pragma vtordisp(2) +struct HasVtorDisp : virtual Base { + virtual ~HasVtorDisp() {} + virtual void Func() {} +}; + +int x[sizeof(HasVtorDisp)]; + +// HasVtorDisp: vtordisp because of pragma right before it. +// +// CHECK: *** Dumping AST Record Layout +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct HasVtorDisp +// CHECK-NEXT: 0 | (HasVtorDisp vftable pointer) +// CHECK-NEXT: 8 | (HasVtorDisp vbtable pointer) +// CHECK-NEXT: 20 | (vtordisp for vbase Base) +// CHECK-NEXT: 24 | struct Base (virtual base) +// CHECK-NEXT: 24 | (Base
Re: [PATCH] D16219: PR8901: attribute "mode" rejected for enums and dependent types
d.zobnin.bugzilla updated this revision to Diff 46521. d.zobnin.bugzilla added a comment. Thanks for the review! Only updated the text of diagnostics, NFC. http://reviews.llvm.org/D16219 Files: include/clang/Basic/Attr.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/AttributeList.h include/clang/Sema/Sema.h lib/Sema/SemaDeclAttr.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CodeGen/attr-mode-enums.c test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp test/Sema/attr-mode-enums.c test/Sema/attr-mode.c test/SemaCXX/attr-mode-tmpl.cpp Index: lib/Sema/SemaTemplateInstantiateDecl.cpp === --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -227,6 +227,14 @@ Attr.getSpellingListIndex()); } +static void +instantiateDependentModeAttr(Sema &S, + const MultiLevelTemplateArgumentList &TemplateArgs, + const ModeAttr &Attr, Decl *New) { + S.AddModeAttr(Attr.getRange(), New, Attr.getMode(), +Attr.getSpellingListIndex(), /*InInstantiation=*/true); +} + void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -265,6 +273,11 @@ continue; } +if (const ModeAttr *Mode = dyn_cast(TmplAttr)) { + instantiateDependentModeAttr(*this, TemplateArgs, *Mode, New); + continue; +} + // Existing DLL attribute on the instantiation takes precedence. if (TmplAttr->getKind() == attr::DLLExport || TmplAttr->getKind() == attr::DLLImport) { Index: lib/Sema/SemaDeclAttr.cpp === --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -3297,6 +3297,8 @@ /// attribute. static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth, bool &IntegerMode, bool &ComplexMode) { + IntegerMode = true; + ComplexMode = false; switch (Str.size()) { case 2: switch (Str[0]) { @@ -3363,9 +3365,15 @@ } IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; - StringRef Str = Name->getName(); + S.AddModeAttr(Attr.getRange(), D, Name, Attr.getAttributeSpellingListIndex()); +} + +void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name, + unsigned SpellingListIndex, bool InInstantiation) { + StringRef Str = Name->getName(); normalizeName(Str); + SourceLocation AttrLoc = AttrRange.getBegin(); unsigned DestWidth = 0; bool IntegerMode = true; @@ -3381,99 +3389,126 @@ if (VectorStringLength && !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) && VectorSize.isPowerOf2()) { - parseModeAttrArg(S, Str.substr(VectorStringLength + 1), DestWidth, + parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth, IntegerMode, ComplexMode); - S.Diag(Attr.getLoc(), diag::warn_vector_mode_deprecated); + // Avoid duplicate warning from template instantiation. + if (!InInstantiation) +Diag(AttrLoc, diag::warn_vector_mode_deprecated); } else { VectorSize = 0; } } if (!VectorSize) -parseModeAttrArg(S, Str, DestWidth, IntegerMode, ComplexMode); +parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode); + + // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t + // and friends, at least with glibc. + // FIXME: Make sure floating-point mappings are accurate + // FIXME: Support XF and TF types + if (!DestWidth) { +Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name; +return; + } QualType OldTy; if (TypedefNameDecl *TD = dyn_cast(D)) OldTy = TD->getUnderlyingType(); - else + else if (EnumDecl *ED = dyn_cast(D)) { +// Something like 'typedef enum { X } __attribute__((mode(XX))) T;'. +// Try to get type from enum declaration, default to int. +OldTy = ED->getIntegerType(); +if (OldTy.isNull()) + OldTy = Context.IntTy; + } else OldTy = cast(D)->getType(); + if (OldTy->isDependentType()) { +D->addAttr(::new (Context) + ModeAttr(AttrRange, Context, Name, SpellingListIndex)); +return; + } + // Base type can also be a vector type (see PR17453). // Distinguish between base type and base element type. QualType OldElemTy = OldTy; if (const VectorType *VT = OldTy->getAs()) OldElemTy = VT->getElementType(); - if (!OldElemTy->getAs() && !OldElemTy->isComplexType()) -S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); + // GCC allows 'mode' attribute on enumeration types (even incomplete), except + // for vector modes. So, 'enum X __attribute__((mode(QI)));' forms a complete + // type, 'enum { A }
[PATCH] D16770: [MS] PR26234: Allow typedef redefinition of equally qualified, sized and aligned types in C
d.zobnin.bugzilla created this revision. d.zobnin.bugzilla added reviewers: rnk, majnemer. d.zobnin.bugzilla added a subscriber: cfe-commits. Allow typedef redefinition with different types in C if the types are equally qualified, sized and aligned. MSVC allows such redefinition, emits warning C4142: "benign redefinition of type" and propagates the type from the first typedef declaration in the entire redeclaration chain. http://reviews.llvm.org/D16770 Files: include/clang/AST/ASTContext.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/ASTContext.cpp lib/Sema/SemaDecl.cpp test/Sema/ms-benign-typedef-redef.c Index: lib/AST/ASTContext.cpp === --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -6723,6 +6723,43 @@ return false; } +bool ASTContext::areMSCompatibleTypesInC(QualType OldType, QualType NewType) { + assert(getLangOpts().MicrosoftExt && + "This routine must be called in Microsoft mode only!"); + assert(!getLangOpts().CPlusPlus && !getLangOpts().ObjC1 && + !getLangOpts().ObjC2 && "This routine must be called in C mode only!"); + + QualType OldCan = getCanonicalType(OldType); + QualType NewCan = getCanonicalType(NewType); + + if (OldCan.getCVRQualifiers() != NewCan.getCVRQualifiers()) +return false; + + if (OldCan->isPointerType() && NewCan->isPointerType()) { +QualType OldPointee = OldType->getPointeeType(); +QualType NewPointee = NewType->getPointeeType(); +// void * and char * are interchangeable. +if ((OldPointee->isCharType() && NewPointee->isVoidType()) || +(OldPointee->isVoidType() && NewPointee->isCharType())) + return true; +return areMSCompatibleTypesInC(OldPointee, NewPointee); + } + + // Enum vs float not allowed. + if ((OldCan->isRealFloatingType() && NewCan->isEnumeralType()) || + (OldCan->isEnumeralType() && NewCan->isRealFloatingType())) +return false; + + if (OldCan->isRealType() && NewCan->isRealType()) { +auto OldTypeInfo = getTypeInfo(OldCan); +auto NewTypeInfo = getTypeInfo(NewCan); +return (OldTypeInfo.Width == NewTypeInfo.Width && +OldTypeInfo.Align == NewTypeInfo.Align); + } + + return false; +} + //===--===// // ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's. //===--===// Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -1842,9 +1842,31 @@ Filter.done(); } +static bool areMSCompatibleTypedefs(TypedefNameDecl *OldTypedef, +TypedefNameDecl *NewTypedef, +ASTContext &Context) { +#ifndef NDEBUG + const LangOptions &Opts = Context.getLangOpts(); + assert(Opts.MicrosoftExt && + "This routine must be called in Microsoft mode only!"); + assert(!Opts.CPlusPlus && !Opts.ObjC1 && !Opts.ObjC2 && + "This routine must be called in C mode only!"); + assert(OldTypedef && NewTypedef && "Expected valid typedef declarations!"); +#endif + + // If both are locally-scoped, emit an error. + if (!OldTypedef->getDeclContext()->isFileContext() && + !NewTypedef->getDeclContext()->isFileContext()) +return false; + + return Context.areMSCompatibleTypesInC(OldTypedef->getUnderlyingType(), + NewTypedef->getUnderlyingType()); +} + bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { QualType OldType; - if (TypedefNameDecl *OldTypedef = dyn_cast(Old)) + TypedefNameDecl *OldTypedef = dyn_cast(Old); + if (OldTypedef) OldType = OldTypedef->getUnderlyingType(); else OldType = Context.getTypeDeclType(Old); @@ -1860,18 +1882,35 @@ New->setInvalidDecl(); return true; } - + if (OldType != NewType && !OldType->isDependentType() && !NewType->isDependentType() && - !Context.hasSameType(OldType, NewType)) { -int Kind = isa(Old) ? 1 : 0; -Diag(New->getLocation(), diag::err_redefinition_different_typedef) - << Kind << NewType << OldType; -if (Old->getLocation().isValid()) - Diag(Old->getLocation(), diag::note_previous_definition); -New->setInvalidDecl(); -return true; + !Context.hasSameType(OldType, NewType)) { +const LangOptions &Opts = Context.getLangOpts(); +bool AllowedAsMicrosoftExtInC = +Opts.MicrosoftExt && !Opts.CPlusPlus && !Opts.ObjC1 && !Opts.ObjC2 && +OldTypedef && areMSCompatibleTypedefs(OldTypedef, New, Context); + +SourceLocation OldLocation = Old->getLocation(); +if (AllowedAsMicrosoftExtInC) { + Diag(New->getLocation(), diag::warn_benign_redefinition_different_typedef) + << NewType << OldType; + if (OldTypedef->isModed()) +New->se
Re: [PATCH] D16630: PR23057: Fix assertion `Val && "isa<> used on a null pointer"' on invalid for-range expression
d.zobnin.bugzilla added inline comments. Comment at: lib/Parse/ParseStmt.cpp:1719-1724 @@ -1718,6 +1718,8 @@ if (ForRange) { +ExprResult CorrectedRange = +Actions.CorrectDelayedTyposInExpr(ForRangeInit.RangeExpr.get()); ForRangeStmt = Actions.ActOnCXXForRangeStmt( getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(), -ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(), +ForRangeInit.ColonLoc, CorrectedRange.get(), T.getCloseLocation(), Sema::BFRK_Build); majnemer wrote: > Does this change effect all of the test cases you've added? If not, I think > it would make sense to split this change out. Yes, this change is needed in all added test cases. Without this we will have an assertion failure in ~Sema(): ``` assert(DelayedTypos.empty() && "Uncorrected typos!"); ``` http://reviews.llvm.org/D16630 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r259492 - Test commit (NFC).
Author: dzobnin Date: Tue Feb 2 06:39:08 2016 New Revision: 259492 URL: http://llvm.org/viewvc/llvm-project?rev=259492&view=rev Log: Test commit (NFC). Modified: cfe/trunk/test/CodeGenCXX/alignment.cpp Modified: cfe/trunk/test/CodeGenCXX/alignment.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/alignment.cpp?rev=259492&r1=259491&r2=259492&view=diff == --- cfe/trunk/test/CodeGenCXX/alignment.cpp (original) +++ cfe/trunk/test/CodeGenCXX/alignment.cpp Tue Feb 2 06:39:08 2016 @@ -32,7 +32,7 @@ namespace test0 { // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]] // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 4 b.onebit = int_source(); - + // CHECK: [[B_P:%.*]] = load [[B]]*, [[B]]** // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4 @@ -60,7 +60,7 @@ namespace test0 { // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]] // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2 c.onebit = int_source(); - + // CHECK: [[C_P:%.*]] = load [[C]]*, [[C]]** // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8* // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r259497 - Fix for PR8901: attribute "mode" rejected for enums and dependent types.
Author: dzobnin Date: Tue Feb 2 07:50:39 2016 New Revision: 259497 URL: http://llvm.org/viewvc/llvm-project?rev=259497&view=rev Log: Fix for PR8901: attribute "mode" rejected for enums and dependent types. Allow "mode" attribute for enum types, except for vector modes, for compatibility with GCC. Support "mode" attribute with dependent types. Differential Revision: http://reviews.llvm.org/D16219 Added: cfe/trunk/test/CodeGen/attr-mode-enums.c cfe/trunk/test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp cfe/trunk/test/Sema/attr-mode-enums.c cfe/trunk/test/SemaCXX/attr-mode-tmpl.cpp Modified: cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Sema/AttributeList.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Sema/SemaDeclAttr.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/test/Sema/attr-mode.c Modified: cfe/trunk/include/clang/Basic/Attr.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=259497&r1=259496&r2=259497&view=diff == --- cfe/trunk/include/clang/Basic/Attr.td (original) +++ cfe/trunk/include/clang/Basic/Attr.td Tue Feb 2 07:50:39 2016 @@ -879,8 +879,8 @@ def MipsInterrupt : InheritableAttr, Tar def Mode : Attr { let Spellings = [GCC<"mode">]; - let Subjects = SubjectList<[Var, TypedefName, Field], ErrorDiag, - "ExpectedVariableFieldOrTypedef">; + let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag, + "ExpectedVariableEnumFieldOrTypedef">; let Args = [IdentifierArgument<"Mode">]; let Documentation = [Undocumented]; } Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=259497&r1=259496&r2=259497&view=diff == --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Feb 2 07:50:39 2016 @@ -2448,7 +2448,7 @@ def warn_attribute_wrong_decl_type : War "variables, functions and classes|Objective-C protocols|" "functions and global variables|structs, unions, and typedefs|structs and typedefs|" "interface or protocol declarations|kernel functions|non-K&R-style functions|" - "variables, fields and typedefs}1">, + "variables, enums, fields and typedefs}1">, InGroup; def err_attribute_wrong_decl_type : Error; def warn_type_attribute_wrong_type : Warning< @@ -2858,6 +2858,8 @@ def warn_vector_mode_deprecated : Warnin InGroup; def err_complex_mode_vector_type : Error< "type of machine mode does not support base vector types">; +def err_enum_mode_vector_type : Error< + "mode %0 is not supported for enumeration types">; def warn_attribute_nonnull_no_pointers : Warning< "'nonnull' attribute applied to function with no pointer arguments">, InGroup; Modified: cfe/trunk/include/clang/Sema/AttributeList.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=259497&r1=259496&r2=259497&view=diff == --- cfe/trunk/include/clang/Sema/AttributeList.h (original) +++ cfe/trunk/include/clang/Sema/AttributeList.h Tue Feb 2 07:50:39 2016 @@ -856,7 +856,7 @@ enum AttributeDeclKind { ExpectedObjectiveCInterfaceOrProtocol, ExpectedKernelFunction, ExpectedFunctionWithProtoType, - ExpectedVariableFieldOrTypedef + ExpectedVariableEnumFieldOrTypedef }; } // end namespace clang Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=259497&r1=259496&r2=259497&view=diff == --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Tue Feb 2 07:50:39 2016 @@ -7750,6 +7750,10 @@ public: void AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads, Expr *MinBlocks, unsigned SpellingListIndex); + /// AddModeAttr - Adds a mode attribute to a particular declaration. + void AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name, + unsigned SpellingListIndex, bool InInstantiation = false); + //======// // C++ Coroutines TS // Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=259497&r1=259496&r2=259497&view=diff == --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Tue Feb 2 07:50:
[PATCH] D16808: [MCU] PR26438: Fix assertion failure on function returning an empty struct or union
d.zobnin.bugzilla created this revision. d.zobnin.bugzilla added reviewers: mkuper, rnk, DavidKreitzer. d.zobnin.bugzilla added a subscriber: cfe-commits. Add missing check for zero-sized type for MCU ABI in order to return zero-sized types (empty structs and unions) via memory. http://reviews.llvm.org/D16808 Files: lib/CodeGen/TargetInfo.cpp test/CodeGen/mcu-struct-return.c Index: lib/CodeGen/TargetInfo.cpp === --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -1010,8 +1010,9 @@ uint64_t Size = Context.getTypeSize(Ty); // For i386, type must be register sized. - // For the MCU ABI, it only needs to be <= 8-byte - if ((IsMCUABI && Size > 64) || (!IsMCUABI && !isRegisterSize(Size))) + // For the MCU ABI, it only needs to be positive <= 8-byte. + if ((IsMCUABI && (Size == 0 || Size > 64)) || + (!IsMCUABI && !isRegisterSize(Size))) return false; if (Ty->isVectorType()) { Index: test/CodeGen/mcu-struct-return.c === --- test/CodeGen/mcu-struct-return.c +++ test/CodeGen/mcu-struct-return.c @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -triple i386-pc-elfiamcu -emit-llvm %s -o - | FileCheck %s + +// Structure that is more than 8 byte. +struct Big { + double a[10]; +}; + +// Empty union with zero size must be returned via memory. +union U1 { +} u1; + +// Too large union (80 bytes) must be returned via memory. +union U2 { + struct Big b; +} u2; + +// Aggregate union, must be returned in register. +union U3 { + int x; +} u3; + +// Empty struct with zero size, must be returned via memory. +struct S1 { +} s1; + +// Aggregate struct, must be returend in register. +struct S2 { + int x; +} s2; + +// CHECK: [[UNION1_TYPE:%.+]] = type {} +// CHECK: [[UNION2_TYPE:%.+]] = type { [[STRUCT_TYPE:%.+]] } +// CHECK: [[STRUCT_TYPE]] = type { [10 x double] } +// CHECK: [[UNION3_TYPE:%.+]] = type { i32 } +// CHECK: [[STRUCT1_TYPE:%.+]] = type {} +// CHECK: [[STRUCT2_TYPE:%.+]] = type { i32 } + +union U1 foo1() { return u1; } +union U2 foo2() { return u2; } +union U3 foo3() { return u3; } +struct S1 bar1() { return s1; } +struct S2 bar2() { return s2; } +// CHECK: define void @foo1([[UNION1_TYPE]]* noalias sret %{{.+}}) +// CHECK: define void @foo2([[UNION2_TYPE]]* noalias sret %{{.+}}) +// CHECK: define i32 @foo3() +// CHECK: define void @bar1([[STRUCT1_TYPE]]* noalias sret %{{.+}}) +// CHECK: define i32 @bar2() + +void run() { + union U1 x1 = foo1(); + union U2 x2 = foo2(); + union U3 x3 = foo3(); + struct S1 y1 = bar1(); + struct S2 y2 = bar2(); + + // CHECK: [[X1:%.+]] = alloca [[UNION1_TYPE]] + // CHECK: [[X2:%.+]] = alloca [[UNION2_TYPE]] + // CHECK: [[X3:%.+]] = alloca [[UNION3_TYPE]] + // CHECK: [[Y1:%.+]] = alloca [[STRUCT1_TYPE]] + // CHECK: [[Y2:%.+]] = alloca [[STRUCT2_TYPE]] + // CHECK: call void @foo1([[UNION1_TYPE]]* sret [[X1]]) + // CHECK: call void @foo2([[UNION2_TYPE]]* sret [[X2]]) + // CHECK: {{.+}} = call i32 @foo3() + // CHECK: call void @bar1([[STRUCT1_TYPE]]* sret [[Y1]]) + // CHECK: {{.+}} = call i32 @bar2() +} Index: lib/CodeGen/TargetInfo.cpp === --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -1010,8 +1010,9 @@ uint64_t Size = Context.getTypeSize(Ty); // For i386, type must be register sized. - // For the MCU ABI, it only needs to be <= 8-byte - if ((IsMCUABI && Size > 64) || (!IsMCUABI && !isRegisterSize(Size))) + // For the MCU ABI, it only needs to be positive <= 8-byte. + if ((IsMCUABI && (Size == 0 || Size > 64)) || + (!IsMCUABI && !isRegisterSize(Size))) return false; if (Ty->isVectorType()) { Index: test/CodeGen/mcu-struct-return.c === --- test/CodeGen/mcu-struct-return.c +++ test/CodeGen/mcu-struct-return.c @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -triple i386-pc-elfiamcu -emit-llvm %s -o - | FileCheck %s + +// Structure that is more than 8 byte. +struct Big { + double a[10]; +}; + +// Empty union with zero size must be returned via memory. +union U1 { +} u1; + +// Too large union (80 bytes) must be returned via memory. +union U2 { + struct Big b; +} u2; + +// Aggregate union, must be returned in register. +union U3 { + int x; +} u3; + +// Empty struct with zero size, must be returned via memory. +struct S1 { +} s1; + +// Aggregate struct, must be returend in register. +struct S2 { + int x; +} s2; + +// CHECK: [[UNION1_TYPE:%.+]] = type {} +// CHECK: [[UNION2_TYPE:%.+]] = type { [[STRUCT_TYPE:%.+]] } +// CHECK: [[STRUCT_TYPE]] = type { [10 x double] } +// CHECK: [[UNION3_TYPE:%.+]] = type { i32 } +// CHECK: [[STRUCT1_TYPE:%.+]] = type {} +// CHECK: [[STRUCT2_TYPE:%.+]] = type { i32 } + +union U1 foo1() { return u1; } +union U2 foo2() { return u2; } +union U3 foo3() { return u3; } +struct S1 bar1() { return s1; } +struct S2 bar2() { return s2;
r259532 - PR23057: Fix assertion `Val && "isa<> used on a null pointer"' on invalid for-range expression.
Author: dzobnin Date: Tue Feb 2 11:33:09 2016 New Revision: 259532 URL: http://llvm.org/viewvc/llvm-project?rev=259532&view=rev Log: PR23057: Fix assertion `Val && "isa<> used on a null pointer"' on invalid for-range expression. Fix the issue discovered by fuzzing (PR23057, comment 18) by handling nullptr in Sema::ActOnCXXForRangeDecl and correct delayed typos in for-range expression before calling Sema::ActOnCXXForRangeStmt. Also fixes PR26288. Differential Revision: http://reviews.llvm.org/D16630 Added: cfe/trunk/test/Parser/cxx-invalid-for-range.cpp Modified: cfe/trunk/lib/Parse/ParseStmt.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp Modified: cfe/trunk/lib/Parse/ParseStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=259532&r1=259531&r2=259532&view=diff == --- cfe/trunk/lib/Parse/ParseStmt.cpp (original) +++ cfe/trunk/lib/Parse/ParseStmt.cpp Tue Feb 2 11:33:09 2016 @@ -1716,9 +1716,11 @@ StmtResult Parser::ParseForStatement(Sou StmtResult ForEachStmt; if (ForRange) { +ExprResult CorrectedRange = +Actions.CorrectDelayedTyposInExpr(ForRangeInit.RangeExpr.get()); ForRangeStmt = Actions.ActOnCXXForRangeStmt( getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(), -ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(), +ForRangeInit.ColonLoc, CorrectedRange.get(), T.getCloseLocation(), Sema::BFRK_Build); // Similarly, we need to do the semantic analysis for a for-range Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=259532&r1=259531&r2=259532&view=diff == --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Feb 2 11:33:09 2016 @@ -9928,6 +9928,10 @@ void Sema::ActOnUninitializedDecl(Decl * } void Sema::ActOnCXXForRangeDecl(Decl *D) { + // If there is no declaration, there was an error parsing it. Ignore it. + if (!D) +return; + VarDecl *VD = dyn_cast(D); if (!VD) { Diag(D->getLocation(), diag::err_for_range_decl_must_be_var); Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp?rev=259532&r1=259531&r2=259532&view=diff == --- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp (original) +++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp Tue Feb 2 11:33:09 2016 @@ -18,6 +18,9 @@ void f() { for (struct S { S(int) {} } s : arr) { // expected-error {{types may not be defined in a for range declaration}} } + for (struct S { S(int) {} } s : Undeclared); // expected-error{{types may not be defined in a for range declaration}} + // expected-error@-1{{use of undeclared identifier 'Undeclared'}} + new struct T {}; // expected-error {{'T' cannot be defined in a type specifier}} new struct A {}; // expected-error {{'A' cannot be defined in a type specifier}} Added: cfe/trunk/test/Parser/cxx-invalid-for-range.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-invalid-for-range.cpp?rev=259532&view=auto == --- cfe/trunk/test/Parser/cxx-invalid-for-range.cpp (added) +++ cfe/trunk/test/Parser/cxx-invalid-for-range.cpp Tue Feb 2 11:33:09 2016 @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// From PR23057 comment #18 (https://llvm.org/bugs/show_bug.cgi?id=23057#c18). + +namespace N { + int X[10]; // expected-note{{declared here +} + +void f1() { + for (auto operator new : X); // expected-error{{'operator new' cannot be the name of a variable or data member}} + // expected-error@-1{{use of undeclared identifier 'X'; did you mean 'N::X'?}} +} + +void f2() { + for (a operator== :) // expected-error{{'operator==' cannot be the name of a variable or data member}} + // expected-error@-1{{expected expression}} + // expected-error@-2{{unknown type name 'a'}} +} // expected-error{{expected statement}} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D16770: [MS] PR26234: Allow typedef redefinition of equally qualified, sized and aligned types in C
d.zobnin.bugzilla updated this revision to Diff 46781. d.zobnin.bugzilla added a comment. Thanks for the review! Updated the patch according to the comments: allowed only integer, enum and pointer types which have the same qualifiers, signedness, width and alignment. Changed the diagnostic text. Please take a look. http://reviews.llvm.org/D16770 Files: include/clang/AST/ASTContext.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/ASTContext.cpp lib/Sema/SemaDecl.cpp test/Sema/ms-benign-typedef-redef.c Index: lib/AST/ASTContext.cpp === --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -6729,6 +6729,42 @@ return false; } +bool ASTContext::areMSCompatibleTypedefTypesInC(QualType OldType, +QualType NewType) { + assert(getLangOpts().MSVCCompat && + "This routine must be called in Microsoft mode only!"); + assert(!getLangOpts().CPlusPlus && !getLangOpts().ObjC1 && + !getLangOpts().ObjC2 && "This routine must be called in C mode only!"); + + QualType OldCan = getCanonicalType(OldType); + QualType NewCan = getCanonicalType(NewType); + + if (OldCan.getCVRQualifiers() != NewCan.getCVRQualifiers()) +return false; + + if (OldCan->isPointerType() && NewCan->isPointerType()) { +QualType OldPointee = OldType->getPointeeType(); +QualType NewPointee = NewType->getPointeeType(); +// void * and char * are interchangeable. +if ((OldPointee->isCharType() && NewPointee->isVoidType()) || +(OldPointee->isVoidType() && NewPointee->isCharType())) + return true; +return areMSCompatibleTypedefTypesInC(OldPointee, NewPointee); + } + + bool EquallySignedInts = (OldCan->isSignedIntegerOrEnumerationType() && +NewCan->isSignedIntegerOrEnumerationType()) || + (OldCan->isUnsignedIntegerOrEnumerationType() && +NewCan->isUnsignedIntegerOrEnumerationType()); + if (!EquallySignedInts) +return false; + + auto OldTypeInfo = getTypeInfo(OldCan); + auto NewTypeInfo = getTypeInfo(NewCan); + return (OldTypeInfo.Width == NewTypeInfo.Width && + OldTypeInfo.Align == NewTypeInfo.Align); +} + //===--===// // ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's. //===--===// Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -1842,9 +1842,30 @@ Filter.done(); } +static bool areMSCompatibleTypedefs(TypedefNameDecl *Old, TypedefNameDecl *New, +ASTContext &Context) { +#ifndef NDEBUG + const LangOptions &Opts = Context.getLangOpts(); + assert(Opts.MSVCCompat && + "This routine must be called in Microsoft mode only!"); + assert(!Opts.CPlusPlus && !Opts.ObjC1 && !Opts.ObjC2 && + "This routine must be called in C mode only!"); + assert(Old && New && "Expected valid typedef declarations!"); +#endif + + // If both are locally-scoped, emit an error. + if (!Old->getDeclContext()->isFileContext() && + !New->getDeclContext()->isFileContext()) +return false; + + return Context.areMSCompatibleTypedefTypesInC(Old->getUnderlyingType(), +New->getUnderlyingType()); +} + bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { QualType OldType; - if (TypedefNameDecl *OldTypedef = dyn_cast(Old)) + auto *OldTypedef = dyn_cast(Old); + if (OldTypedef) OldType = OldTypedef->getUnderlyingType(); else OldType = Context.getTypeDeclType(Old); @@ -1860,18 +1881,35 @@ New->setInvalidDecl(); return true; } - + if (OldType != NewType && !OldType->isDependentType() && !NewType->isDependentType() && - !Context.hasSameType(OldType, NewType)) { -int Kind = isa(Old) ? 1 : 0; -Diag(New->getLocation(), diag::err_redefinition_different_typedef) - << Kind << NewType << OldType; -if (Old->getLocation().isValid()) - Diag(Old->getLocation(), diag::note_previous_definition); -New->setInvalidDecl(); -return true; + !Context.hasSameType(OldType, NewType)) { +const LangOptions &Opts = Context.getLangOpts(); +bool AllowedAsMicrosoftExtInC = +Opts.MSVCCompat && !Opts.CPlusPlus && !Opts.ObjC1 && !Opts.ObjC2 && +OldTypedef && areMSCompatibleTypedefs(OldTypedef, New, Context); + +SourceLocation OldLocation = Old->getLocation(); +if (AllowedAsMicrosoftExtInC) { + Diag(New->getLocation(), diag::warn_int_typedef_redefinition_ignored) + << NewType << OldType; + if (OldTypedef->isModed()) +New->setModedTypeSourceInfo(OldTypedef->getTypeSourceInfo(), +
Re: [PATCH] D16770: [MS] PR26234: Allow typedef redefinition of equally qualified, sized and aligned types in C
d.zobnin.bugzilla marked 5 inline comments as done. Comment at: include/clang/AST/ASTContext.h:1772-1783 @@ -1771,1 +1771,14 @@ + /// Return true is the given typedef types are compatible in C from MSVC's + /// point of view. + // + // Conditions: + // 1. Both typedef types are either integer, enumeral or pointers; + // 2. Both typedef types have the same qualifiers and signedness; + // 3. Both typedef types have the same size and alignment; + // 4. If pointers: + // 4.1. Levels of pointers are equal; + // 4.2. Pointee types are MSVC-compatible OR + // 4.3. One type points to void and another points to char. + bool areMSCompatibleTypedefTypesInC(QualType OldType, QualType NewType); + By the way, MSVC allows to redefine not anly typedefs, but variables as well (under the same conditions as typedefs): ``` int x; long x; ``` Typedef redefinition seems to be just an example of MSVC's permissive behavior. The same for return types, etc. So, do you think we need to compatible with MSVC, for example, also considering only integer types? Comment at: include/clang/Basic/DiagnosticSemaKinds.td:4267-4269 @@ -4266,1 +4266,5 @@ InGroup>; +def warn_int_typedef_redefinition_ignored : ExtWarn< + "ignoring conflicting integer typedef redefinition%diff{ ($ vs $)|}0,1 " + "as a Microsoft extension; types have the same width and signedness">, + InGroup; Done. I also tried to move the phrase "types have the same ..." to a note, but I thought the only warning was better. http://reviews.llvm.org/D16770 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D16770: [MS] PR26234: Allow typedef redefinition of equally qualified, sized and aligned types in C
d.zobnin.bugzilla marked 2 inline comments as done. d.zobnin.bugzilla added a comment. @thakis, it is needed to be able to compile SPEC2000: 255.vortex. http://reviews.llvm.org/D16770 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D16808: [MCU] PR26438: Fix assertion failure on function returning an empty struct or union
d.zobnin.bugzilla added a comment. Thank you for the review! David, I started from the assertion failure and was going up the call stack trying to understand what should be changed to make the assertion go away. In shouldReturnTypeInRegister() function there is isRegisterSize(Size) check for i386, which returns false for 0-sized types, so I naively assumed that for MCU we missed the 0-case check. I must have read the ABI more carefully... While searching for a correct solution for this, I saw that 'void' return type is handled in classifyReturnType() by returning ABIArgInfo::getIgnore(). According to the comments: /// Ignore - Ignore the argument (treat as void). Useful for void and /// empty structs. Ignore, Does it mean that we can treat empty structs and unions in return type as void in this case? http://reviews.llvm.org/D16808 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D16808: [MCU] PR26438: Fix assertion failure on function returning an empty struct or union
d.zobnin.bugzilla updated this revision to Diff 47333. d.zobnin.bugzilla added a comment. Thank you for your reply! Added a check for empty struct/union to treat them as void, updated the test accordingly. Please take a look. http://reviews.llvm.org/D16808 Files: lib/CodeGen/TargetInfo.cpp test/CodeGen/mcu-struct-return.c Index: lib/CodeGen/TargetInfo.cpp === --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -364,7 +364,7 @@ static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) { const RecordType *RT = T->getAs(); if (!RT) -return 0; +return false; const RecordDecl *RD = RT->getDecl(); if (RD->hasFlexibleArrayMember()) return false; @@ -1119,6 +1119,10 @@ if (!IsRetSmallStructInRegABI && !RetTy->isAnyComplexType()) return getIndirectReturnResult(RetTy, State); +// Ignore empty structs/unions. +if (isEmptyRecord(getContext(), RetTy, true)) + return ABIArgInfo::getIgnore(); + // Small structures which are register sized are generally returned // in a register. if (shouldReturnTypeInRegister(RetTy, getContext())) { Index: test/CodeGen/mcu-struct-return.c === --- test/CodeGen/mcu-struct-return.c +++ test/CodeGen/mcu-struct-return.c @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -triple i386-pc-elfiamcu -emit-llvm %s -o - | FileCheck %s + +// Structure that is more than 8 byte. +struct Big { + double a[10]; +}; + +// Empty union with zero size must be returned as void. +union U1 { +} u1; + +// Too large union (80 bytes) must be returned via memory. +union U2 { + struct Big b; +} u2; + +// Must be returned in register. +union U3 { + int x; +} u3; + +// Empty struct with zero size, must be returned as void. +struct S1 { +} s1; + +// Must be returend in register. +struct S2 { + int x; +} s2; + +// CHECK: [[UNION1_TYPE:%.+]] = type {} +// CHECK: [[UNION2_TYPE:%.+]] = type { [[STRUCT_TYPE:%.+]] } +// CHECK: [[STRUCT_TYPE]] = type { [10 x double] } +// CHECK: [[UNION3_TYPE:%.+]] = type { i32 } +// CHECK: [[STRUCT1_TYPE:%.+]] = type {} +// CHECK: [[STRUCT2_TYPE:%.+]] = type { i32 } + +union U1 foo1() { return u1; } +union U2 foo2() { return u2; } +union U3 foo3() { return u3; } +struct S1 bar1() { return s1; } +struct S2 bar2() { return s2; } +struct S1 bar3(union U1 u) { return s1; } +// CHECK: define void @foo1() +// CHECK: define void @foo2([[UNION2_TYPE]]* noalias sret %{{.+}}) +// CHECK: define i32 @foo3() +// CHECK: define void @bar1() +// CHECK: define i32 @bar2() +// CHECK: define void @bar3() + +void run() { + union U1 x1 = foo1(); + union U2 x2 = foo2(); + union U3 x3 = foo3(); + struct S1 y1 = bar1(); + struct S2 y2 = bar2(); + struct S1 y3 = bar3(x1); + + // CHECK: [[X1:%.+]] = alloca [[UNION1_TYPE]] + // CHECK: [[X2:%.+]] = alloca [[UNION2_TYPE]] + // CHECK: [[X3:%.+]] = alloca [[UNION3_TYPE]] + // CHECK: [[Y1:%.+]] = alloca [[STRUCT1_TYPE]] + // CHECK: [[Y2:%.+]] = alloca [[STRUCT2_TYPE]] + // CHECK: call void @foo1() + // CHECK: call void @foo2([[UNION2_TYPE]]* sret [[X2]]) + // CHECK: {{.+}} = call i32 @foo3() + // CHECK: call void @bar1() + // CHECK: {{.+}} = call i32 @bar2() + // CHECK: call void @bar3() +} Index: lib/CodeGen/TargetInfo.cpp === --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -364,7 +364,7 @@ static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) { const RecordType *RT = T->getAs(); if (!RT) -return 0; +return false; const RecordDecl *RD = RT->getDecl(); if (RD->hasFlexibleArrayMember()) return false; @@ -1119,6 +1119,10 @@ if (!IsRetSmallStructInRegABI && !RetTy->isAnyComplexType()) return getIndirectReturnResult(RetTy, State); +// Ignore empty structs/unions. +if (isEmptyRecord(getContext(), RetTy, true)) + return ABIArgInfo::getIgnore(); + // Small structures which are register sized are generally returned // in a register. if (shouldReturnTypeInRegister(RetTy, getContext())) { Index: test/CodeGen/mcu-struct-return.c === --- test/CodeGen/mcu-struct-return.c +++ test/CodeGen/mcu-struct-return.c @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -triple i386-pc-elfiamcu -emit-llvm %s -o - | FileCheck %s + +// Structure that is more than 8 byte. +struct Big { + double a[10]; +}; + +// Empty union with zero size must be returned as void. +union U1 { +} u1; + +// Too large union (80 bytes) must be returned via memory. +union U2 { + struct Big b; +} u2; + +// Must be returned in register. +union U3 { + int x; +} u3; + +// Empty struct with zero size, must be returned as void. +struct S1 { +} s1; + +// Must be returend in register. +struct S2 { + int x; +} s2; + +// CHECK: [[UNION1_TYPE:%.+]] = type {} +// CHECK:
r260373 - Fix assertion "Chunk.Kind == DeclaratorChunk::Function" with attributed type.
Author: dzobnin Date: Wed Feb 10 05:23:48 2016 New Revision: 260373 URL: http://llvm.org/viewvc/llvm-project?rev=260373&view=rev Log: Fix assertion "Chunk.Kind == DeclaratorChunk::Function" with attributed type. This patch is to upgrade FunctionTypeUnwrapper for correct processing of AttributedType. Fixes PR25786. Patch by Alexander Makarov. Differential Revision: http://reviews.llvm.org/D15373 Added: cfe/trunk/test/CodeGen/pr25786.c cfe/trunk/test/Sema/pr25786.c Modified: cfe/trunk/lib/Sema/SemaType.cpp Modified: cfe/trunk/lib/Sema/SemaType.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=260373&r1=260372&r2=260373&view=diff == --- cfe/trunk/lib/Sema/SemaType.cpp (original) +++ cfe/trunk/lib/Sema/SemaType.cpp Wed Feb 10 05:23:48 2016 @@ -5370,6 +5370,7 @@ namespace { struct FunctionTypeUnwrapper { enum WrapKind { Desugar, + Attributed, Parens, Pointer, BlockPointer, @@ -5402,6 +5403,9 @@ namespace { } else if (isa(Ty)) { T = cast(Ty)->getPointeeType(); Stack.push_back(Reference); +} else if (isa(Ty)) { + T = cast(Ty)->getEquivalentType(); + Stack.push_back(Attributed); } else { const Type *DTy = Ty->getUnqualifiedDesugaredType(); if (Ty == DTy) { @@ -5450,6 +5454,9 @@ namespace { // information. return wrap(C, Old->getUnqualifiedDesugaredType(), I); + case Attributed: +return wrap(C, cast(Old)->getEquivalentType(), I); + case Parens: { QualType New = wrap(C, cast(Old)->getInnerType(), I); return C.getParenType(New); Added: cfe/trunk/test/CodeGen/pr25786.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/pr25786.c?rev=260373&view=auto == --- cfe/trunk/test/CodeGen/pr25786.c (added) +++ cfe/trunk/test/CodeGen/pr25786.c Wed Feb 10 05:23:48 2016 @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-OK + +void (__attribute__((regparm(3), stdcall)) *pf) (); +void (__attribute__((regparm(2), stdcall)) foo)(int a) { +} +// CHECK: @pf = common global void (...)* null +// CHECK: define void @foo(i32 %a) + +// CHECK-OK: @pf = common global void (...)* null +// CHECK-OK: define x86_stdcallcc void @foo(i32 inreg %a) Added: cfe/trunk/test/Sema/pr25786.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/pr25786.c?rev=260373&view=auto == --- cfe/trunk/test/Sema/pr25786.c (added) +++ cfe/trunk/test/Sema/pr25786.c Wed Feb 10 05:23:48 2016 @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -DTEST -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fsyntax-only -verify %s + +#if TEST +void (__attribute__((regparm(3), stdcall)) *pf) (); //expected-warning {{calling convention 'stdcall' ignored for this target}} +void (__attribute__((regparm(2), stdcall)) foo)(int a) { //expected-warning {{calling convention 'stdcall' ignored for this target}} +} +#else +//expected-no-diagnostics +void (__attribute__((regparm(3), stdcall)) *pf) (); +void (__attribute__((regparm(2), stdcall)) foo)(int a) {} +#endif ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r260510 - [MCU] Fix assertion failure on function returning empty union.
Author: dzobnin Date: Thu Feb 11 05:26:03 2016 New Revision: 260510 URL: http://llvm.org/viewvc/llvm-project?rev=260510&view=rev Log: [MCU] Fix assertion failure on function returning empty union. Treat empty struct/union in return type as void for MCU ABI. PR26438. Differential Revision: http://reviews.llvm.org/D16808 Added: cfe/trunk/test/CodeGen/mcu-struct-return.c Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=260510&r1=260509&r2=260510&view=diff == --- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original) +++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Thu Feb 11 05:26:03 2016 @@ -364,7 +364,7 @@ static bool isEmptyField(ASTContext &Con static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) { const RecordType *RT = T->getAs(); if (!RT) -return 0; +return false; const RecordDecl *RD = RT->getDecl(); if (RD->hasFlexibleArrayMember()) return false; @@ -1119,6 +1119,10 @@ ABIArgInfo X86_32ABIInfo::classifyReturn if (!IsRetSmallStructInRegABI && !RetTy->isAnyComplexType()) return getIndirectReturnResult(RetTy, State); +// Ignore empty structs/unions. +if (isEmptyRecord(getContext(), RetTy, true)) + return ABIArgInfo::getIgnore(); + // Small structures which are register sized are generally returned // in a register. if (shouldReturnTypeInRegister(RetTy, getContext())) { Added: cfe/trunk/test/CodeGen/mcu-struct-return.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/mcu-struct-return.c?rev=260510&view=auto == --- cfe/trunk/test/CodeGen/mcu-struct-return.c (added) +++ cfe/trunk/test/CodeGen/mcu-struct-return.c Thu Feb 11 05:26:03 2016 @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -triple i386-pc-elfiamcu -emit-llvm %s -o - | FileCheck %s + +// Structure that is more than 8 byte. +struct Big { + double a[10]; +}; + +// Empty union with zero size must be returned as void. +union U1 { +} u1; + +// Too large union (80 bytes) must be returned via memory. +union U2 { + struct Big b; +} u2; + +// Must be returned in register. +union U3 { + int x; +} u3; + +// Empty struct with zero size, must be returned as void. +struct S1 { +} s1; + +// Must be returend in register. +struct S2 { + int x; +} s2; + +// CHECK: [[UNION1_TYPE:%.+]] = type {} +// CHECK: [[UNION2_TYPE:%.+]] = type { [[STRUCT_TYPE:%.+]] } +// CHECK: [[STRUCT_TYPE]] = type { [10 x double] } +// CHECK: [[UNION3_TYPE:%.+]] = type { i32 } +// CHECK: [[STRUCT1_TYPE:%.+]] = type {} +// CHECK: [[STRUCT2_TYPE:%.+]] = type { i32 } + +union U1 foo1() { return u1; } +union U2 foo2() { return u2; } +union U3 foo3() { return u3; } +struct S1 bar1() { return s1; } +struct S2 bar2() { return s2; } +struct S1 bar3(union U1 u) { return s1; } +// CHECK: define void @foo1() +// CHECK: define void @foo2([[UNION2_TYPE]]* noalias sret %{{.+}}) +// CHECK: define i32 @foo3() +// CHECK: define void @bar1() +// CHECK: define i32 @bar2() +// CHECK: define void @bar3() + +void run() { + union U1 x1 = foo1(); + union U2 x2 = foo2(); + union U3 x3 = foo3(); + struct S1 y1 = bar1(); + struct S2 y2 = bar2(); + struct S1 y3 = bar3(x1); + + // CHECK: [[X1:%.+]] = alloca [[UNION1_TYPE]] + // CHECK: [[X2:%.+]] = alloca [[UNION2_TYPE]] + // CHECK: [[X3:%.+]] = alloca [[UNION3_TYPE]] + // CHECK: [[Y1:%.+]] = alloca [[STRUCT1_TYPE]] + // CHECK: [[Y2:%.+]] = alloca [[STRUCT2_TYPE]] + // CHECK: call void @foo1() + // CHECK: call void @foo2([[UNION2_TYPE]]* sret [[X2]]) + // CHECK: {{.+}} = call i32 @foo3() + // CHECK: call void @bar1() + // CHECK: {{.+}} = call i32 @bar2() + // CHECK: call void @bar3() +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D18700: [Inline asm][GCC compatibility] Handle %v-prefixed code in inline assembly
d.zobnin.bugzilla added a comment. This is just a weekly friendly ping. Please take a look at the new patch! Thank you, Denis Zobnin http://reviews.llvm.org/D18700 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r267866 - [MS] Improved implementation of MS stack pragmas (vtordisp, *_seg)
Author: dzobnin Date: Thu Apr 28 05:13:18 2016 New Revision: 267866 URL: http://llvm.org/viewvc/llvm-project?rev=267866&view=rev Log: [MS] Improved implementation of MS stack pragmas (vtordisp, *_seg) Rework implementation of several MS pragmas that use internal stack: vtordisp, {bss|code|const|data}_seg. This patch: 1. Makes #pragma vtordisp use PragmaStack class as *_seg pragmas do; 2. Fixes "#pragma vtordisp()" behavior: it shouldn't affect stack; 3. Saves/restores the stacks on enter/exit a C++ method body. Modified: cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Parse/ParsePragma.cpp cfe/trunk/lib/Parse/ParseStmt.cpp cfe/trunk/lib/Sema/Sema.cpp cfe/trunk/lib/Sema/SemaAttr.cpp cfe/trunk/test/CodeGenCXX/sections.cpp cfe/trunk/test/SemaCXX/pragma-vtordisp.cpp Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=267866&r1=267865&r2=267866&view=diff == --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Thu Apr 28 05:13:18 2016 @@ -327,40 +327,21 @@ public: LangOptions::PragmaMSPointersToMembersKind MSPointerToMemberRepresentationMethod; - enum PragmaVtorDispKind { -PVDK_Push, ///< #pragma vtordisp(push, mode) -PVDK_Set, ///< #pragma vtordisp(mode) -PVDK_Pop, ///< #pragma vtordisp(pop) -PVDK_Reset ///< #pragma vtordisp() - }; - - enum PragmaMsStackAction { -PSK_Reset,// #pragma () -PSK_Set, // #pragma ("name") -PSK_Push, // #pragma (push[, id]) -PSK_Push_Set, // #pragma (push[, id], "name") -PSK_Pop, // #pragma (pop[, id]) -PSK_Pop_Set, // #pragma (pop[, id], "name") - }; - - /// \brief Whether to insert vtordisps prior to virtual bases in the Microsoft - /// C++ ABI. Possible values are 0, 1, and 2, which mean: - /// - /// 0: Suppress all vtordisps - /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial - ///structors - /// 2: Always insert vtordisps to support RTTI on partially constructed - ///objects - /// - /// The stack always has at least one element in it. - SmallVector VtorDispModeStack; - /// Stack of active SEH __finally scopes. Can be empty. SmallVector CurrentSEHFinally; /// \brief Source location for newly created implicit MSInheritanceAttrs SourceLocation ImplicitMSInheritanceAttrLoc; + enum PragmaMsStackAction { +PSK_Reset = 0x0,// #pragma () +PSK_Set = 0x1,// #pragma (value) +PSK_Push = 0x2,// #pragma (push[, id]) +PSK_Pop = 0x4,// #pragma (pop[, id]) +PSK_Push_Set = PSK_Push | PSK_Set, // #pragma (push[, id], value) +PSK_Pop_Set = PSK_Pop | PSK_Set, // #pragma (pop[, id], value) + }; + template struct PragmaStack { struct Slot { @@ -377,18 +358,84 @@ public: PragmaMsStackAction Action, llvm::StringRef StackSlotLabel, ValueType Value); -explicit PragmaStack(const ValueType &Value) - : CurrentValue(Value) {} + +// MSVC seems to add artificial slots to #pragma stacks on entering a C++ +// method body to restore the stacks on exit, so it works like this: +// +// struct S { +// #pragma (push, InternalPragmaSlot, ) +// void Method {} +// #pragma (pop, InternalPragmaSlot) +// }; +// +// It works even with #pragma vtordisp, although MSVC doesn't support +// #pragma vtordisp(push [, id], n) +// syntax. +// +// Push / pop a named sentinel slot. +void SentinelAction(PragmaMsStackAction Action, StringRef Label) { + assert((Action == PSK_Push || Action == PSK_Pop) && + "Can only push / pop #pragma stack sentinels!"); + Act(CurrentPragmaLocation, Action, Label, CurrentValue); +} + +// Constructors. +explicit PragmaStack(const ValueType &Default) +: DefaultValue(Default), CurrentValue(Default) {} + SmallVector Stack; +ValueType DefaultValue; // Value used for PSK_Reset action. ValueType CurrentValue; SourceLocation CurrentPragmaLocation; }; // FIXME: We should serialize / deserialize these if they occur in a PCH (but // we shouldn't do so if they're in a module). + + /// \brief Whether to insert vtordisps prior to virtual bases in the Microsoft + /// C++ ABI. Possible values are 0, 1, and 2, which mean: + /// + /// 0: Suppress all vtordisps + /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial + ///structors + /// 2: Always insert vtordisps to support RTTI on partially constructed + ///objects + PragmaStack VtorDispStack; PragmaStack DataSegStack; PragmaStack BSSSegStack; PragmaStack ConstSegStack; PragmaStack CodeSegStack; + // TODO:
r267870 - Revert "[MS] Improved implementation of MS stack pragmas (vtordisp, *_seg)"
Author: dzobnin Date: Thu Apr 28 06:32:10 2016 New Revision: 267870 URL: http://llvm.org/viewvc/llvm-project?rev=267870&view=rev Log: Revert "[MS] Improved implementation of MS stack pragmas (vtordisp, *_seg)" This reverts commit r267866. Modified: cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Parse/ParsePragma.cpp cfe/trunk/lib/Parse/ParseStmt.cpp cfe/trunk/lib/Sema/Sema.cpp cfe/trunk/lib/Sema/SemaAttr.cpp cfe/trunk/test/CodeGenCXX/sections.cpp cfe/trunk/test/SemaCXX/pragma-vtordisp.cpp Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=267870&r1=267869&r2=267870&view=diff == --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Thu Apr 28 06:32:10 2016 @@ -327,21 +327,40 @@ public: LangOptions::PragmaMSPointersToMembersKind MSPointerToMemberRepresentationMethod; + enum PragmaVtorDispKind { +PVDK_Push, ///< #pragma vtordisp(push, mode) +PVDK_Set, ///< #pragma vtordisp(mode) +PVDK_Pop, ///< #pragma vtordisp(pop) +PVDK_Reset ///< #pragma vtordisp() + }; + + enum PragmaMsStackAction { +PSK_Reset,// #pragma () +PSK_Set, // #pragma ("name") +PSK_Push, // #pragma (push[, id]) +PSK_Push_Set, // #pragma (push[, id], "name") +PSK_Pop, // #pragma (pop[, id]) +PSK_Pop_Set, // #pragma (pop[, id], "name") + }; + + /// \brief Whether to insert vtordisps prior to virtual bases in the Microsoft + /// C++ ABI. Possible values are 0, 1, and 2, which mean: + /// + /// 0: Suppress all vtordisps + /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial + ///structors + /// 2: Always insert vtordisps to support RTTI on partially constructed + ///objects + /// + /// The stack always has at least one element in it. + SmallVector VtorDispModeStack; + /// Stack of active SEH __finally scopes. Can be empty. SmallVector CurrentSEHFinally; /// \brief Source location for newly created implicit MSInheritanceAttrs SourceLocation ImplicitMSInheritanceAttrLoc; - enum PragmaMsStackAction { -PSK_Reset = 0x0,// #pragma () -PSK_Set = 0x1,// #pragma (value) -PSK_Push = 0x2,// #pragma (push[, id]) -PSK_Pop = 0x4,// #pragma (pop[, id]) -PSK_Push_Set = PSK_Push | PSK_Set, // #pragma (push[, id], value) -PSK_Pop_Set = PSK_Pop | PSK_Set, // #pragma (pop[, id], value) - }; - template struct PragmaStack { struct Slot { @@ -358,84 +377,18 @@ public: PragmaMsStackAction Action, llvm::StringRef StackSlotLabel, ValueType Value); - -// MSVC seems to add artificial slots to #pragma stacks on entering a C++ -// method body to restore the stacks on exit, so it works like this: -// -// struct S { -// #pragma (push, InternalPragmaSlot, ) -// void Method {} -// #pragma (pop, InternalPragmaSlot) -// }; -// -// It works even with #pragma vtordisp, although MSVC doesn't support -// #pragma vtordisp(push [, id], n) -// syntax. -// -// Push / pop a named sentinel slot. -void SentinelAction(PragmaMsStackAction Action, StringRef Label) { - assert((Action == PSK_Push || Action == PSK_Pop) && - "Can only push / pop #pragma stack sentinels!"); - Act(CurrentPragmaLocation, Action, Label, CurrentValue); -} - -// Constructors. -explicit PragmaStack(const ValueType &Default) -: DefaultValue(Default), CurrentValue(Default) {} - +explicit PragmaStack(const ValueType &Value) + : CurrentValue(Value) {} SmallVector Stack; -ValueType DefaultValue; // Value used for PSK_Reset action. ValueType CurrentValue; SourceLocation CurrentPragmaLocation; }; // FIXME: We should serialize / deserialize these if they occur in a PCH (but // we shouldn't do so if they're in a module). - - /// \brief Whether to insert vtordisps prior to virtual bases in the Microsoft - /// C++ ABI. Possible values are 0, 1, and 2, which mean: - /// - /// 0: Suppress all vtordisps - /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial - ///structors - /// 2: Always insert vtordisps to support RTTI on partially constructed - ///objects - PragmaStack VtorDispStack; PragmaStack DataSegStack; PragmaStack BSSSegStack; PragmaStack ConstSegStack; PragmaStack CodeSegStack; - // TODO: Change implementation of #pragma pack to use PragmaStack<> approach. - - // RAII object to psuh / pop sentinel slots for all MS #pragma stacks. - // Actions should be performed only if we enter / exit a C++ method body. - class PragmaStackSentinelRAII { - public: -PragmaStack
r268029 - Recommit "[MS] Improved implementation of stack pragmas (vtordisp, *_seg)"
Author: dzobnin Date: Fri Apr 29 06:27:00 2016 New Revision: 268029 URL: http://llvm.org/viewvc/llvm-project?rev=268029&view=rev Log: Recommit "[MS] Improved implementation of stack pragmas (vtordisp, *_seg)" Slightly updated version, double-checked build and tests. Improve implementation of MS pragmas that use stack + compatibility fixes. This patch: 1. Changes implementation of #pragma vtordisp to use PragmaStack class that other stack pragmas use; 2. Fixes "#pragma vtordisp()" behavior - it shouldn't affect the stack; 3. Supports "save-restore" of pragma stacks on enter / exit a C++ method body, as MSVC does. TODO: 1. Change implementation of #pragma pack to use the same approach; 2. Introduce diagnostics on popping named stack slots, as MSVC does. Reviewers: rnk, thakis Differential revision: http://reviews.llvm.org/D19361 Modified: cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Parse/ParsePragma.cpp cfe/trunk/lib/Parse/ParseStmt.cpp cfe/trunk/lib/Sema/Sema.cpp cfe/trunk/lib/Sema/SemaAttr.cpp cfe/trunk/test/CodeGenCXX/sections.cpp cfe/trunk/test/SemaCXX/pragma-vtordisp.cpp Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=268029&r1=268028&r2=268029&view=diff == --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Fri Apr 29 06:27:00 2016 @@ -327,40 +327,21 @@ public: LangOptions::PragmaMSPointersToMembersKind MSPointerToMemberRepresentationMethod; - enum PragmaVtorDispKind { -PVDK_Push, ///< #pragma vtordisp(push, mode) -PVDK_Set, ///< #pragma vtordisp(mode) -PVDK_Pop, ///< #pragma vtordisp(pop) -PVDK_Reset ///< #pragma vtordisp() - }; - - enum PragmaMsStackAction { -PSK_Reset,// #pragma () -PSK_Set, // #pragma ("name") -PSK_Push, // #pragma (push[, id]) -PSK_Push_Set, // #pragma (push[, id], "name") -PSK_Pop, // #pragma (pop[, id]) -PSK_Pop_Set, // #pragma (pop[, id], "name") - }; - - /// \brief Whether to insert vtordisps prior to virtual bases in the Microsoft - /// C++ ABI. Possible values are 0, 1, and 2, which mean: - /// - /// 0: Suppress all vtordisps - /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial - ///structors - /// 2: Always insert vtordisps to support RTTI on partially constructed - ///objects - /// - /// The stack always has at least one element in it. - SmallVector VtorDispModeStack; - /// Stack of active SEH __finally scopes. Can be empty. SmallVector CurrentSEHFinally; /// \brief Source location for newly created implicit MSInheritanceAttrs SourceLocation ImplicitMSInheritanceAttrLoc; + enum PragmaMsStackAction { +PSK_Reset = 0x0,// #pragma () +PSK_Set = 0x1,// #pragma (value) +PSK_Push = 0x2,// #pragma (push[, id]) +PSK_Pop = 0x4,// #pragma (pop[, id]) +PSK_Push_Set = PSK_Push | PSK_Set, // #pragma (push[, id], value) +PSK_Pop_Set = PSK_Pop | PSK_Set, // #pragma (pop[, id], value) + }; + template struct PragmaStack { struct Slot { @@ -377,18 +358,66 @@ public: PragmaMsStackAction Action, llvm::StringRef StackSlotLabel, ValueType Value); -explicit PragmaStack(const ValueType &Value) - : CurrentValue(Value) {} + +// MSVC seems to add artificial slots to #pragma stacks on entering a C++ +// method body to restore the stacks on exit, so it works like this: +// +// struct S { +// #pragma (push, InternalPragmaSlot, ) +// void Method {} +// #pragma (pop, InternalPragmaSlot) +// }; +// +// It works even with #pragma vtordisp, although MSVC doesn't support +// #pragma vtordisp(push [, id], n) +// syntax. +// +// Push / pop a named sentinel slot. +void SentinelAction(PragmaMsStackAction Action, StringRef Label) { + assert((Action == PSK_Push || Action == PSK_Pop) && + "Can only push / pop #pragma stack sentinels!"); + Act(CurrentPragmaLocation, Action, Label, CurrentValue); +} + +// Constructors. +explicit PragmaStack(const ValueType &Default) +: DefaultValue(Default), CurrentValue(Default) {} + SmallVector Stack; +ValueType DefaultValue; // Value used for PSK_Reset action. ValueType CurrentValue; SourceLocation CurrentPragmaLocation; }; // FIXME: We should serialize / deserialize these if they occur in a PCH (but // we shouldn't do so if they're in a module). + + /// \brief Whether to insert vtordisps prior to virtual bases in the Microsoft + /// C++ ABI. Possible values are 0, 1, and 2, which mean: + /// + /// 0: Suppress all vtordisps + /// 1
Re: [PATCH] D19361: [MS] Improved implementation of MS stack pragmas (vtordisp, *_seg)
d.zobnin.bugzilla added a comment. Reid, thanks for review! I've changed the patch according to your comments and also moved implementation of RAII object to SemaAttr.cpp file (implementation in header broke many buildbots). Nico, I will look at serialization and try to implement the desired behavior, thank you! Repository: rL LLVM http://reviews.llvm.org/D19361 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D18700: [Inline asm][GCC compatibility] Handle %v-prefixed code in inline assembly
d.zobnin.bugzilla updated this revision to Diff 55581. d.zobnin.bugzilla added a comment. Herald added a subscriber: joker.eph. Updated the patch after r266292 commit: [ASTImporter] Implement some expression-related AST node import. http://reviews.llvm.org/D18700 Files: include/clang/AST/Stmt.h lib/AST/ASTImporter.cpp lib/AST/Stmt.cpp lib/Sema/SemaStmtAsm.cpp test/CodeGen/avx-v-modifier-inline-asm.cpp Index: lib/AST/Stmt.cpp === --- lib/AST/Stmt.cpp +++ lib/AST/Stmt.cpp @@ -632,6 +632,14 @@ CurPtr = NameEnd+1; continue; +} else if (*Begin == 'v') { + // GCC accepts code staring with "%v", e. g. "%vpcmpestri" and transforms + // it into "vpcmpestri" instruction if target processor supports AVX and + // into "pcmpestri" otherwise. + if (SupportsAVX) +CurStringPiece = "v" + CurStringPiece; + CurStringPiece += EscapedChar; + continue; } DiagOffs = CurPtr-StrStart-1; @@ -682,13 +690,15 @@ //===--===// GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, - bool issimple, bool isvolatile, unsigned numoutputs, - unsigned numinputs, IdentifierInfo **names, - StringLiteral **constraints, Expr **exprs, - StringLiteral *asmstr, unsigned numclobbers, - StringLiteral **clobbers, SourceLocation rparenloc) - : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, -numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) { + bool issimple, bool isvolatile, bool supportsavx, + unsigned numoutputs, unsigned numinputs, + IdentifierInfo **names, StringLiteral **constraints, + Expr **exprs, StringLiteral *asmstr, + unsigned numclobbers, StringLiteral **clobbers, + SourceLocation rparenloc) +: AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, + numinputs, numclobbers), + RParenLoc(rparenloc), AsmStr(asmstr), SupportsAVX(supportsavx) { unsigned NumExprs = NumOutputs + NumInputs; Index: lib/AST/ASTImporter.cpp === --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -4833,6 +4833,7 @@ Importer.Import(S->getAsmLoc()), S->isSimple(), S->isVolatile(), +S->getSupportsAVX(), S->getNumOutputs(), S->getNumInputs(), Names.data(), Index: lib/Sema/SemaStmtAsm.cpp === --- lib/Sema/SemaStmtAsm.cpp +++ lib/Sema/SemaStmtAsm.cpp @@ -138,6 +138,75 @@ return false; } +// Collect all target features specified for the current context by the "target" +// attribute. Start from current DeclContext and iterate its parents until we +// find a function context. +static void CollectTargetFeatures(Sema &S, + std::vector &TargetFeatures, + StringRef &TargetCPU) { + DeclContext *DC = S.CurContext; + + auto Collect = [&TargetFeatures, &TargetCPU](const FunctionDecl *FD) { +if (!FD) + return; +if (const auto *TA = FD->getAttr()) { + TargetAttr::ParsedTargetAttr ParsedAttr = TA->parse(); + TargetFeatures.insert(TargetFeatures.begin(), ParsedAttr.first.begin(), +ParsedAttr.first.end()); + if (TargetCPU == "") +TargetCPU = ParsedAttr.second; +} + }; + + // Climb up the tree of nested DeclContext-s, collecting the target features. + while (true) { +if (isa(DC) || isa(DC) || isa(DC)) { + DC = DC->getParent(); +} else if (const auto *MD = dyn_cast(DC)) { + // Check if it's a lambda and collect its target features. + if (MD->getOverloadedOperator() == OO_Call && + cast(DC->getParent())->isLambda()) { +Collect(MD); + } + DC = DC->getParent()->getParent(); +} else { + // It's the nearest function, collect its features and break. + Collect(dyn_cast(DC)); + break; +} + } +} + +// Check whether a particular target feature is enabled in current context, +// either by command-line options or by __attribute__((__target__("..."))), +// applied to any surrounding lambda or function. +static bool TargetFeatureEnabled(Sema &S, StringRef Feature) { + const TargetInfo &TI = S.Context.getTargetInfo(); + llvm::StringMap FeatureMap; + StringRef TargetCPU; + std::vector TargetFeatures; + + // Collect target features and CPU from surrounding declarations. + CollectTargetFeatures(S, TargetFeatures, TargetCPU); + + // Don't forget to add command-line features and CPU (lowest priority). + TargetFeatures.insert(TargetFeatures.begin
[PATCH] D19727: [MS] Improved implementation #pragma pack (MS pragmas, part 2)
d.zobnin.bugzilla created this revision. d.zobnin.bugzilla added a reviewer: rnk. d.zobnin.bugzilla added subscribers: thakis, cfe-commits. An attempt to make implementation of #pragma pack consistent with other "stack" pragmas. Also modifies #pragma options align, since it shares the stack with #pragma pack. It is the first item from todo list in http://reviews.llvm.org/D19361 The patch doesn't change compiler's behavior, so the tests are not modified. I'm planning to rework the pragmas' diagnostics in next patch -- it should be a common feature of all "stack" pragmas. http://reviews.llvm.org/D19727 Files: include/clang/Sema/Sema.h lib/Parse/ParsePragma.cpp lib/Sema/Sema.cpp lib/Sema/SemaAttr.cpp Index: lib/Parse/ParsePragma.cpp === --- lib/Parse/ParsePragma.cpp +++ lib/Parse/ParsePragma.cpp @@ -337,11 +337,9 @@ namespace { struct PragmaPackInfo { - Sema::PragmaPackKind Kind; - IdentifierInfo *Name; + Sema::PragmaMsStackAction Action; + StringRef SlotLabel; Token Alignment; - SourceLocation LParenLoc; - SourceLocation RParenLoc; }; } // end anonymous namespace @@ -356,8 +354,8 @@ if (Alignment.isInvalid()) return; } - Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc, - Info->LParenLoc, Info->RParenLoc); + Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel, + Alignment.get()); } void Parser::HandlePragmaMSStruct() { @@ -962,11 +960,10 @@ return; } - Sema::PragmaPackKind Kind = Sema::PPK_Default; - IdentifierInfo *Name = nullptr; + Sema::PragmaMsStackAction Action = Sema::PSK_Reset; + StringRef SlotLabel; Token Alignment; Alignment.startToken(); - SourceLocation LParenLoc = Tok.getLocation(); PP.Lex(Tok); if (Tok.is(tok::numeric_constant)) { Alignment = Tok; @@ -976,18 +973,18 @@ // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting // the push/pop stack. // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4) -if (PP.getLangOpts().ApplePragmaPack) - Kind = Sema::PPK_Push; +Action = +PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set; } else if (Tok.is(tok::identifier)) { const IdentifierInfo *II = Tok.getIdentifierInfo(); if (II->isStr("show")) { - Kind = Sema::PPK_Show; + Action = Sema::PSK_Show; PP.Lex(Tok); } else { if (II->isStr("push")) { -Kind = Sema::PPK_Push; +Action = Sema::PSK_Push; } else if (II->isStr("pop")) { -Kind = Sema::PPK_Pop; +Action = Sema::PSK_Pop; } else { PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack"; return; @@ -998,11 +995,12 @@ PP.Lex(Tok); if (Tok.is(tok::numeric_constant)) { + Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); Alignment = Tok; PP.Lex(Tok); } else if (Tok.is(tok::identifier)) { - Name = Tok.getIdentifierInfo(); + SlotLabel = Tok.getIdentifierInfo()->getName(); PP.Lex(Tok); if (Tok.is(tok::comma)) { @@ -1013,6 +1011,7 @@ return; } +Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); Alignment = Tok; PP.Lex(Tok); @@ -1027,7 +1026,7 @@ // In MSVC/gcc, #pragma pack() resets the alignment without affecting // the push/pop stack. // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop). -Kind = Sema::PPK_Pop; +Action = Sema::PSK_Pop; } if (Tok.isNot(tok::r_paren)) { @@ -1044,11 +1043,9 @@ PragmaPackInfo *Info = PP.getPreprocessorAllocator().Allocate(1); - Info->Kind = Kind; - Info->Name = Name; + Info->Action = Action; + Info->SlotLabel = SlotLabel; Info->Alignment = Alignment; - Info->LParenLoc = LParenLoc; - Info->RParenLoc = RParenLoc; MutableArrayRef Toks(PP.getPreprocessorAllocator().Allocate(1), 1); Index: lib/Sema/Sema.cpp === --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -79,12 +79,13 @@ Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), CollectStats(false), CodeCompleter(CodeCompleter), CurContext(nullptr), OriginalLexicalContext(nullptr), -PackContext(nullptr), MSStructPragmaOn(false), +MSStructPragmaOn(false), MSPointerToMemberRepresentationMethod( LangOpts.getMSPointerToMemberRepresentationMethod()), VtorDispStack(MSVtorDispAttr::Mode(LangOpts.VtorDispMode)), -DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr), -CodeSegStack(nullptr), CurInitSeg(nullptr), VisContext(nullptr), +PackStack(0), DataSegStack(nullptr), BSSSegStack(nullptr), +ConstSegStack(nullptr), CodeSegStack(n
Re: [PATCH] D19727: [MS] Improved implementation #pragma pack (MS pragmas, part 2)
d.zobnin.bugzilla added inline comments. Comment at: lib/Sema/SemaAttr.cpp:277-278 @@ -276,4 @@ - // empty. - Diag(PragmaLoc, diag::warn_pragma_pop_failed) - << "pack" << (Name ? "no record matching name" : "stack empty"); - Here I removed the "no record matching name" diagnostics, which wasn't covered by any test. I'm going to rework and restore it in future patch. http://reviews.llvm.org/D19727 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r268085 - [MS] Make #pragma pack use PragmaStack<> class.
Author: dzobnin Date: Fri Apr 29 13:17:40 2016 New Revision: 268085 URL: http://llvm.org/viewvc/llvm-project?rev=268085&view=rev Log: [MS] Make #pragma pack use PragmaStack<> class. Make implementation of #pragma pack consistent with other "stack" pragmas. Use PragmaStack<> class instead of old representation of internal stack. Don't change compiler's behavior. TODO: 1. Introduce diagnostics on popping named slots from pragma stacks. Reviewer: rnk Differential revision: http://reviews.llvm.org/D19727 Modified: cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Parse/ParsePragma.cpp cfe/trunk/lib/Sema/Sema.cpp cfe/trunk/lib/Sema/SemaAttr.cpp Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=268085&r1=268084&r2=268085&view=diff == --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Fri Apr 29 13:17:40 2016 @@ -317,10 +317,6 @@ public: /// This is used as part of a hack to omit that class from ADL results. DeclarationName VAListTagName; - /// PackContext - Manages the stack for \#pragma pack. An alignment - /// of 0 indicates default alignment. - void *PackContext; // Really a "PragmaPackStack*" - bool MSStructPragmaOn; // True when \#pragma ms_struct on /// \brief Controls member pointer representation format under the MS ABI. @@ -338,6 +334,7 @@ public: PSK_Set = 0x1,// #pragma (value) PSK_Push = 0x2,// #pragma (push[, id]) PSK_Pop = 0x4,// #pragma (pop[, id]) +PSK_Show = 0x8,// #pragma (show) -- only for "pack"! PSK_Push_Set = PSK_Push | PSK_Set, // #pragma (push[, id], value) PSK_Pop_Set = PSK_Pop | PSK_Set, // #pragma (pop[, id], value) }; @@ -400,11 +397,15 @@ public: /// 2: Always insert vtordisps to support RTTI on partially constructed ///objects PragmaStack VtorDispStack; + // #pragma pack. + // Sentinel to represent when the stack is set to mac68k alignment. + static const unsigned kMac68kAlignmentSentinel = ~0U; + PragmaStack PackStack; + // Segment #pragmas. PragmaStack DataSegStack; PragmaStack BSSSegStack; PragmaStack ConstSegStack; PragmaStack CodeSegStack; - // TODO: Change implementation of #pragma pack to use PragmaStack<> approach. // RAII object to push / pop sentinel slots for all MS #pragma stacks. // Actions should be performed only if we enter / exit a C++ method body. @@ -7658,20 +7659,9 @@ public: void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, SourceLocation PragmaLoc); - enum PragmaPackKind { -PPK_Default, // #pragma pack([n]) -PPK_Show,// #pragma pack(show), only supported by MSVC. -PPK_Push,// #pragma pack(push, [identifier], [n]) -PPK_Pop // #pragma pack(pop, [identifier], [n]) - }; - /// ActOnPragmaPack - Called on well formed \#pragma pack(...). - void ActOnPragmaPack(PragmaPackKind Kind, - IdentifierInfo *Name, - Expr *Alignment, - SourceLocation PragmaLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc); + void ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action, + StringRef SlotLabel, Expr *Alignment); /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off]. void ActOnPragmaMSStruct(PragmaMSStructKind Kind); Modified: cfe/trunk/lib/Parse/ParsePragma.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParsePragma.cpp?rev=268085&r1=268084&r2=268085&view=diff == --- cfe/trunk/lib/Parse/ParsePragma.cpp (original) +++ cfe/trunk/lib/Parse/ParsePragma.cpp Fri Apr 29 13:17:40 2016 @@ -337,11 +337,9 @@ void Parser::HandlePragmaVisibility() { namespace { struct PragmaPackInfo { - Sema::PragmaPackKind Kind; - IdentifierInfo *Name; + Sema::PragmaMsStackAction Action; + StringRef SlotLabel; Token Alignment; - SourceLocation LParenLoc; - SourceLocation RParenLoc; }; } // end anonymous namespace @@ -356,8 +354,8 @@ void Parser::HandlePragmaPack() { if (Alignment.isInvalid()) return; } - Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc, - Info->LParenLoc, Info->RParenLoc); + Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel, + Alignment.get()); } void Parser::HandlePragmaMSStruct() { @@ -962,11 +960,10 @@ void PragmaPackHandler::HandlePragma(Pre return; } - Sema::PragmaPackKind Kind = Sema::PPK_Default; - IdentifierInfo *Name = nullptr; + Sema::PragmaMsStackAction Action = Sema::PSK_Reset; + StringRef SlotL
r268129 - [NFC] Initialize a variable to make buildbot green.
Author: dzobnin Date: Fri Apr 29 17:50:16 2016 New Revision: 268129 URL: http://llvm.org/viewvc/llvm-project?rev=268129&view=rev Log: [NFC] Initialize a variable to make buildbot green. In r268085 "[MS] Make #pragma pack use PragmaStack<> class." there was an uninitialized variable 'Alignment', which caused the following failure: http://lab.llvm.org:8011/builders/sanitizer-ppc64be-linux/builds/1758 Zero-initialize the variable to fix this failure. Modified: cfe/trunk/lib/Sema/SemaAttr.cpp Modified: cfe/trunk/lib/Sema/SemaAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAttr.cpp?rev=268129&r1=268128&r2=268129&view=diff == --- cfe/trunk/lib/Sema/SemaAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaAttr.cpp Fri Apr 29 17:50:16 2016 @@ -78,7 +78,7 @@ void Sema::AddMsStructLayoutForRecord(Re void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, SourceLocation PragmaLoc) { PragmaMsStackAction Action = Sema::PSK_Reset; - unsigned Alignment; + unsigned Alignment = 0; switch (Kind) { // For all targets we support native and natural are the same. // ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D18652: [Inline asm] Correctly parse GCC-style asm line following MS-style asm line
d.zobnin.bugzilla created this revision. d.zobnin.bugzilla added a reviewer: echristo. d.zobnin.bugzilla added a subscriber: cfe-commits. Clang fails to compile the following code: void f() { __asm mov ebx, ecx __asm__("movl %ecx, %edx"); } reporting unexpected token "__asm__" at start of statement. Quit parsing MS-style assembly if the following statement has GCC style to handle such code. http://reviews.llvm.org/D18652 Files: lib/Parse/ParseStmtAsm.cpp test/CodeGen/inline-asm-mixed-style.c Index: lib/Parse/ParseStmtAsm.cpp === --- lib/Parse/ParseStmtAsm.cpp +++ lib/Parse/ParseStmtAsm.cpp @@ -417,9 +417,10 @@ // If this is a single-line __asm, we're done, except if the next // line begins with an __asm too, in which case we finish a comment // if needed and then keep processing the next line as a single -// line __asm. +// line __asm. Also break if the next __asm is followed by an '(' - +// GCC-style asm. bool isAsm = Tok.is(tok::kw_asm); -if (SingleLineMode && !isAsm) +if (SingleLineMode && (!isAsm || NextToken().is(tok::l_paren))) break; // We're no longer in a comment. InAsmComment = false; Index: test/CodeGen/inline-asm-mixed-style.c === --- test/CodeGen/inline-asm-mixed-style.c +++ test/CodeGen/inline-asm-mixed-style.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -fasm-blocks -fsyntax-only -verify %s +// expected-no-diagnostics +// RUN: %clang_cc1 -triple i386-unknown-unknown -fasm-blocks -emit-llvm -S %s -o - | FileCheck %s + +void f() { + __asm mov eax, ebx + __asm mov ebx, ecx + __asm__("movl %ecx, %edx"); + + // CHECK: movl%ebx, %eax + // CHECK: movl%ecx, %ebx + // CHECK: movl%ecx, %edx +} Index: lib/Parse/ParseStmtAsm.cpp === --- lib/Parse/ParseStmtAsm.cpp +++ lib/Parse/ParseStmtAsm.cpp @@ -417,9 +417,10 @@ // If this is a single-line __asm, we're done, except if the next // line begins with an __asm too, in which case we finish a comment // if needed and then keep processing the next line as a single -// line __asm. +// line __asm. Also break if the next __asm is followed by an '(' - +// GCC-style asm. bool isAsm = Tok.is(tok::kw_asm); -if (SingleLineMode && !isAsm) +if (SingleLineMode && (!isAsm || NextToken().is(tok::l_paren))) break; // We're no longer in a comment. InAsmComment = false; Index: test/CodeGen/inline-asm-mixed-style.c === --- test/CodeGen/inline-asm-mixed-style.c +++ test/CodeGen/inline-asm-mixed-style.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -fasm-blocks -fsyntax-only -verify %s +// expected-no-diagnostics +// RUN: %clang_cc1 -triple i386-unknown-unknown -fasm-blocks -emit-llvm -S %s -o - | FileCheck %s + +void f() { + __asm mov eax, ebx + __asm mov ebx, ecx + __asm__("movl %ecx, %edx"); + + // CHECK: movl%ebx, %eax + // CHECK: movl%ecx, %ebx + // CHECK: movl%ecx, %edx +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D18657: Propagate missing empty exception spec from function declared in system header
d.zobnin.bugzilla created this revision. d.zobnin.bugzilla added reviewers: doug.gregor, rjmccall. d.zobnin.bugzilla added a subscriber: cfe-commits. If new function is missing empty exception specification "throw()" and "throw()" came from system header, don't emit errors. It is already implemented in Clang, but taking into account only last redeclaration of a function. Look for declaration in system header up to the first declaration in redeclaration chain, as GCC seems to do. This patch enables compilation of Facebook/ds2 application. http://reviews.llvm.org/D18657 Files: lib/Sema/SemaExceptionSpec.cpp test/SemaCXX/Inputs/malloc.h test/SemaCXX/builtin-exception-spec.cpp Index: lib/Sema/SemaExceptionSpec.cpp === --- lib/Sema/SemaExceptionSpec.cpp +++ lib/Sema/SemaExceptionSpec.cpp @@ -254,9 +254,15 @@ // to many libc functions as an optimization. Unfortunately, that // optimization isn't permitted by the C++ standard, so we're forced // to work around it here. - if (MissingEmptyExceptionSpecification && NewProto && - (Old->getLocation().isInvalid() || - Context.getSourceManager().isInSystemHeader(Old->getLocation())) && + bool IsFromSystemHeader = false; + for (const FunctionDecl *Prev = Old; Prev; Prev = Prev->getPreviousDecl()) +if (Prev->getLocation().isInvalid() || +Context.getSourceManager().isInSystemHeader(Prev->getLocation())) { + IsFromSystemHeader = true; + break; +} + + if (MissingEmptyExceptionSpecification && NewProto && IsFromSystemHeader && Old->isExternC()) { New->setType(Context.getFunctionType( NewProto->getReturnType(), NewProto->getParamTypes(), Index: test/SemaCXX/builtin-exception-spec.cpp === --- test/SemaCXX/builtin-exception-spec.cpp +++ test/SemaCXX/builtin-exception-spec.cpp @@ -4,4 +4,7 @@ extern "C" { void *malloc(__SIZE_TYPE__); + +void MyFunc() __attribute__((__weak__)); +void MyFunc() { return; } } Index: test/SemaCXX/Inputs/malloc.h === --- test/SemaCXX/Inputs/malloc.h +++ test/SemaCXX/Inputs/malloc.h @@ -1,3 +1,5 @@ extern "C" { extern void *malloc (__SIZE_TYPE__ __size) throw () __attribute__ ((__malloc__)) ; + +void MyFunc() throw(); } Index: lib/Sema/SemaExceptionSpec.cpp === --- lib/Sema/SemaExceptionSpec.cpp +++ lib/Sema/SemaExceptionSpec.cpp @@ -254,9 +254,15 @@ // to many libc functions as an optimization. Unfortunately, that // optimization isn't permitted by the C++ standard, so we're forced // to work around it here. - if (MissingEmptyExceptionSpecification && NewProto && - (Old->getLocation().isInvalid() || - Context.getSourceManager().isInSystemHeader(Old->getLocation())) && + bool IsFromSystemHeader = false; + for (const FunctionDecl *Prev = Old; Prev; Prev = Prev->getPreviousDecl()) +if (Prev->getLocation().isInvalid() || +Context.getSourceManager().isInSystemHeader(Prev->getLocation())) { + IsFromSystemHeader = true; + break; +} + + if (MissingEmptyExceptionSpecification && NewProto && IsFromSystemHeader && Old->isExternC()) { New->setType(Context.getFunctionType( NewProto->getReturnType(), NewProto->getParamTypes(), Index: test/SemaCXX/builtin-exception-spec.cpp === --- test/SemaCXX/builtin-exception-spec.cpp +++ test/SemaCXX/builtin-exception-spec.cpp @@ -4,4 +4,7 @@ extern "C" { void *malloc(__SIZE_TYPE__); + +void MyFunc() __attribute__((__weak__)); +void MyFunc() { return; } } Index: test/SemaCXX/Inputs/malloc.h === --- test/SemaCXX/Inputs/malloc.h +++ test/SemaCXX/Inputs/malloc.h @@ -1,3 +1,5 @@ extern "C" { extern void *malloc (__SIZE_TYPE__ __size) throw () __attribute__ ((__malloc__)) ; + +void MyFunc() throw(); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D18698: [C11] PR24451: Allow restrict _Atomic pointers
d.zobnin.bugzilla created this revision. d.zobnin.bugzilla added a reviewer: rsmith. d.zobnin.bugzilla added a subscriber: cfe-commits. Treat _Atomic pointers as pointer types (check value type of AtomicType) in case of handling the "restrict" qualifier. Accept such code (so does GCC): int * restrict _Atomic p; http://reviews.llvm.org/D18698 Files: lib/Sema/SemaType.cpp test/Misc/ast-dump-restrict-atomic.c Index: lib/Sema/SemaType.cpp === --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -1663,12 +1663,18 @@ if (T.isNull()) return QualType(); + QualType OriginalType = T; + // Enforce C99 6.7.3p2: "Types other than pointer types derived from // object or incomplete types shall not be restrict-qualified." if (Qs.hasRestrict()) { unsigned DiagID = 0; QualType ProblemTy; +// Handle code like "int * _Atomic restrict p". +if (const AtomicType *AtomicT = T->getAs()) + T = AtomicT->getValueType(); + if (T->isAnyPointerType() || T->isReferenceType() || T->isMemberPointerType()) { QualType EltTy; @@ -1696,7 +1702,7 @@ } } - return Context.getQualifiedType(T, Qs); + return Context.getQualifiedType(OriginalType, Qs); } QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, Index: test/Misc/ast-dump-restrict-atomic.c === --- test/Misc/ast-dump-restrict-atomic.c +++ test/Misc/ast-dump-restrict-atomic.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c11 -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -std=c11 -verify %s +// expected-no-diagnostics + +int * _Atomic restrict a; +int * restrict _Atomic b; +int _Atomic * restrict c; +volatile _Atomic int * restrict _Atomic const * restrict d; + +// CHECK: a '__restrict _Atomic(int *)' +// CHECK: b '__restrict _Atomic(int *)' +// CHECK: c '_Atomic(int) *__restrict' +// CHECK: d 'const __restrict _Atomic(volatile _Atomic(int) *) *__restrict' Index: lib/Sema/SemaType.cpp === --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -1663,12 +1663,18 @@ if (T.isNull()) return QualType(); + QualType OriginalType = T; + // Enforce C99 6.7.3p2: "Types other than pointer types derived from // object or incomplete types shall not be restrict-qualified." if (Qs.hasRestrict()) { unsigned DiagID = 0; QualType ProblemTy; +// Handle code like "int * _Atomic restrict p". +if (const AtomicType *AtomicT = T->getAs()) + T = AtomicT->getValueType(); + if (T->isAnyPointerType() || T->isReferenceType() || T->isMemberPointerType()) { QualType EltTy; @@ -1696,7 +1702,7 @@ } } - return Context.getQualifiedType(T, Qs); + return Context.getQualifiedType(OriginalType, Qs); } QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, Index: test/Misc/ast-dump-restrict-atomic.c === --- test/Misc/ast-dump-restrict-atomic.c +++ test/Misc/ast-dump-restrict-atomic.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c11 -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -std=c11 -verify %s +// expected-no-diagnostics + +int * _Atomic restrict a; +int * restrict _Atomic b; +int _Atomic * restrict c; +volatile _Atomic int * restrict _Atomic const * restrict d; + +// CHECK: a '__restrict _Atomic(int *)' +// CHECK: b '__restrict _Atomic(int *)' +// CHECK: c '_Atomic(int) *__restrict' +// CHECK: d 'const __restrict _Atomic(volatile _Atomic(int) *) *__restrict' ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D18700: [Inline asm][GCC compatibility] Handle %v-prefixed code in inline assembly
d.zobnin.bugzilla created this revision. d.zobnin.bugzilla added a reviewer: echristo. d.zobnin.bugzilla added a subscriber: cfe-commits. Handle an inline assembly feature of GCC: code prefixed with "%v", e. g. "%vpcmpestri" is transformed into "vpcmpestri" instruction if target supports AVX and into "pcmpestri" otherwise. Given the code: ``` void f(void* arg) { __asm__ ("%vpcmpestri $0, (%1), %2" : "=c"(arg) : "r"(arg), "x"(arg)); } ``` "gcc -c test.c -o test.o" produces ``` movq -0x10(%rbp),%xmm0 pcmpestri $0x0,(%rax),%xmm0 ``` While "gcc -c -march=corei7-avx test.c -o test.o" produces ``` vmovq %rdx,%xmm0 vpcmpestri $0x0,(%rax),%xmm0 ``` http://reviews.llvm.org/D18700 Files: lib/AST/Stmt.cpp test/CodeGen/avx-inline-asm.c Index: lib/AST/Stmt.cpp === --- lib/AST/Stmt.cpp +++ lib/AST/Stmt.cpp @@ -632,6 +632,14 @@ CurPtr = NameEnd+1; continue; +} else if (*Begin == 'v') { + // GCC accepts code staring with "%v", e. g. "%vpcmpestri" and transforms + // it into "vpcmpestri" instruction if target processor supports AVX and + // into "pcmpestri" otherwise. + if (C.getTargetInfo().hasFeature("avx")) +CurStringPiece = "v" + CurStringPiece; + CurStringPiece += EscapedChar; + continue; } DiagOffs = CurPtr-StrStart-1; Index: test/CodeGen/avx-inline-asm.c === --- test/CodeGen/avx-inline-asm.c +++ test/CodeGen/avx-inline-asm.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux -target-feature +avx -emit-llvm -S %s -o - | FileCheck %s -check-prefix=CHECK-AVX +// RUN: %clang_cc1 -triple x86_64-unknown-linux -emit-llvm -S %s -o - | FileCheck %s + +void f(void* arg) +{ + __asm__ ("%vpcmpestri $0, (%1), %2" + : "=c"(arg) + : "r"(arg), "x"(arg)); + + // CHECK: pcmpestri + // CHECK-AVX: vpcmpestri +} Index: lib/AST/Stmt.cpp === --- lib/AST/Stmt.cpp +++ lib/AST/Stmt.cpp @@ -632,6 +632,14 @@ CurPtr = NameEnd+1; continue; +} else if (*Begin == 'v') { + // GCC accepts code staring with "%v", e. g. "%vpcmpestri" and transforms + // it into "vpcmpestri" instruction if target processor supports AVX and + // into "pcmpestri" otherwise. + if (C.getTargetInfo().hasFeature("avx")) +CurStringPiece = "v" + CurStringPiece; + CurStringPiece += EscapedChar; + continue; } DiagOffs = CurPtr-StrStart-1; Index: test/CodeGen/avx-inline-asm.c === --- test/CodeGen/avx-inline-asm.c +++ test/CodeGen/avx-inline-asm.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux -target-feature +avx -emit-llvm -S %s -o - | FileCheck %s -check-prefix=CHECK-AVX +// RUN: %clang_cc1 -triple x86_64-unknown-linux -emit-llvm -S %s -o - | FileCheck %s + +void f(void* arg) +{ + __asm__ ("%vpcmpestri $0, (%1), %2" + : "=c"(arg) + : "r"(arg), "x"(arg)); + + // CHECK: pcmpestri + // CHECK-AVX: vpcmpestri +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D18698: [C11] PR24451: Allow restrict _Atomic pointers
d.zobnin.bugzilla added a comment. Richard, thank you for the review and explanation! I don't have any examples of useful code using this extension, I was trying to fix the PR... So, do you think we should add this GCC extension to Clang (with a proper warning, of course) for compatibility reasons, or it will be better to close PR24451 and abandon this review? Thank you, Denis Zobnin http://reviews.llvm.org/D18698 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D18657: Propagate missing empty exception spec from function declared in system header
d.zobnin.bugzilla added a comment. Friendly ping, please take a look. Thank you, Denis Zobnin http://reviews.llvm.org/D18657 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D18700: [Inline asm][GCC compatibility] Handle %v-prefixed code in inline assembly
d.zobnin.bugzilla updated this revision to Diff 53400. d.zobnin.bugzilla added a comment. Eric, thank you for the review! I've renamed the test, but have also made it a .cpp file for the reasons described below. You are right -- GCC looks at "target" attribute applied to the function in which inline asm exists. But GCC seems to take into account lambda's attributes as well, if asm statement is inside a lambda. To be correct, GCC seems to collect all target features from command line, function and lambda's attributes, so such code: void f8(void *x) __attribute__((__target__("no-avx"))); void f8(void *x) { auto g1 = [](void *arg) __attribute__((__target__("avx2"))) { auto g2 = [&arg]() __attribute__((__target__("no-mmx"))) { int a = 10, b; __asm__ ("%vmovq (%%rbp), %%xmm0" : "=r"(b) : "r"(a) : "%eax"); }; g2(); }; g1(x); } will produce "vmovq" instruction regardless of command line arguments because of g1's attribute. I tried several approaches to implement this behavior and came up with this patch, please take a look! http://reviews.llvm.org/D18700 Files: include/clang/AST/Stmt.h lib/AST/Stmt.cpp lib/Sema/SemaStmtAsm.cpp test/CodeGen/avx-v-modifier-inline-asm.cpp Index: lib/AST/Stmt.cpp === --- lib/AST/Stmt.cpp +++ lib/AST/Stmt.cpp @@ -632,6 +632,14 @@ CurPtr = NameEnd+1; continue; +} else if (*Begin == 'v') { + // GCC accepts code staring with "%v", e. g. "%vpcmpestri" and transforms + // it into "vpcmpestri" instruction if target processor supports AVX and + // into "pcmpestri" otherwise. + if (SupportsAVX) +CurStringPiece = "v" + CurStringPiece; + CurStringPiece += EscapedChar; + continue; } DiagOffs = CurPtr-StrStart-1; @@ -682,13 +690,15 @@ //===--===// GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, - bool issimple, bool isvolatile, unsigned numoutputs, - unsigned numinputs, IdentifierInfo **names, - StringLiteral **constraints, Expr **exprs, - StringLiteral *asmstr, unsigned numclobbers, - StringLiteral **clobbers, SourceLocation rparenloc) - : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, -numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) { + bool issimple, bool isvolatile, bool supportsavx, + unsigned numoutputs, unsigned numinputs, + IdentifierInfo **names, StringLiteral **constraints, + Expr **exprs, StringLiteral *asmstr, + unsigned numclobbers, StringLiteral **clobbers, + SourceLocation rparenloc) +: AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, + numinputs, numclobbers), + RParenLoc(rparenloc), AsmStr(asmstr), SupportsAVX(supportsavx) { unsigned NumExprs = NumOutputs + NumInputs; Index: lib/Sema/SemaStmtAsm.cpp === --- lib/Sema/SemaStmtAsm.cpp +++ lib/Sema/SemaStmtAsm.cpp @@ -138,6 +138,75 @@ return false; } +// Collect all target features specified for the current context by the "target" +// attribute. Start from current DeclContext and iterate its parents until we +// find a function context. +static void CollectTargetFeatures(Sema &S, + std::vector &TargetFeatures, + StringRef &TargetCPU) { + DeclContext *DC = S.CurContext; + + auto Collect = [&TargetFeatures, &TargetCPU](const FunctionDecl *FD) { +if (!FD) + return; +if (const auto *TA = FD->getAttr()) { + TargetAttr::ParsedTargetAttr ParsedAttr = TA->parse(); + TargetFeatures.insert(TargetFeatures.begin(), ParsedAttr.first.begin(), +ParsedAttr.first.end()); + if (TargetCPU == "") +TargetCPU = ParsedAttr.second; +} + }; + + // Climb up the tree of nested DeclContext-s, collecting the target features. + while (true) { +if (isa(DC) || isa(DC) || isa(DC)) { + DC = DC->getParent(); +} else if (const auto *MD = dyn_cast(DC)) { + // Check if it's a lambda and collect its target features. + if (MD->getOverloadedOperator() == OO_Call && + cast(DC->getParent())->isLambda()) { +Collect(MD); + } + DC = DC->getParent()->getParent(); +} else { + // It's the nearest function, collect its features and break. + Collect(dyn_cast(DC)); + break; +} + } +} + +// Check whether a particular target feature is enabled in current context, +// either by command-line options or by __attribute__((__target__("..."))), +// applied to any surrounding lambda or func
Re: [PATCH] D18657: Propagate missing empty exception spec from function declared in system header
d.zobnin.bugzilla updated this revision to Diff 53414. d.zobnin.bugzilla added a comment. John, thanks for the review! Please take a look at the updated patch -- did I understand your comments correctly? The test passes and ds2 application is compiled successfully. Thank you, Denis Zobnin http://reviews.llvm.org/D18657 Files: lib/Sema/SemaExceptionSpec.cpp test/SemaCXX/Inputs/malloc.h test/SemaCXX/builtin-exception-spec.cpp Index: lib/Sema/SemaExceptionSpec.cpp === --- lib/Sema/SemaExceptionSpec.cpp +++ lib/Sema/SemaExceptionSpec.cpp @@ -254,10 +254,10 @@ // to many libc functions as an optimization. Unfortunately, that // optimization isn't permitted by the C++ standard, so we're forced // to work around it here. - if (MissingEmptyExceptionSpecification && NewProto && - (Old->getLocation().isInvalid() || - Context.getSourceManager().isInSystemHeader(Old->getLocation())) && - Old->isExternC()) { + FunctionDecl *First = Old->getFirstDecl(); + if (MissingEmptyExceptionSpecification && NewProto && First->isExternC() && + (First->getLocation().isInvalid() || + Context.getSourceManager().isInSystemHeader(First->getLocation( { New->setType(Context.getFunctionType( NewProto->getReturnType(), NewProto->getParamTypes(), NewProto->getExtProtoInfo().withExceptionSpec(EST_DynamicNone))); Index: test/SemaCXX/builtin-exception-spec.cpp === --- test/SemaCXX/builtin-exception-spec.cpp +++ test/SemaCXX/builtin-exception-spec.cpp @@ -4,4 +4,7 @@ extern "C" { void *malloc(__SIZE_TYPE__); + +void MyFunc() __attribute__((__weak__)); +void MyFunc() { return; } } Index: test/SemaCXX/Inputs/malloc.h === --- test/SemaCXX/Inputs/malloc.h +++ test/SemaCXX/Inputs/malloc.h @@ -1,3 +1,5 @@ extern "C" { extern void *malloc (__SIZE_TYPE__ __size) throw () __attribute__ ((__malloc__)) ; + +void MyFunc() throw(); } Index: lib/Sema/SemaExceptionSpec.cpp === --- lib/Sema/SemaExceptionSpec.cpp +++ lib/Sema/SemaExceptionSpec.cpp @@ -254,10 +254,10 @@ // to many libc functions as an optimization. Unfortunately, that // optimization isn't permitted by the C++ standard, so we're forced // to work around it here. - if (MissingEmptyExceptionSpecification && NewProto && - (Old->getLocation().isInvalid() || - Context.getSourceManager().isInSystemHeader(Old->getLocation())) && - Old->isExternC()) { + FunctionDecl *First = Old->getFirstDecl(); + if (MissingEmptyExceptionSpecification && NewProto && First->isExternC() && + (First->getLocation().isInvalid() || + Context.getSourceManager().isInSystemHeader(First->getLocation( { New->setType(Context.getFunctionType( NewProto->getReturnType(), NewProto->getParamTypes(), NewProto->getExtProtoInfo().withExceptionSpec(EST_DynamicNone))); Index: test/SemaCXX/builtin-exception-spec.cpp === --- test/SemaCXX/builtin-exception-spec.cpp +++ test/SemaCXX/builtin-exception-spec.cpp @@ -4,4 +4,7 @@ extern "C" { void *malloc(__SIZE_TYPE__); + +void MyFunc() __attribute__((__weak__)); +void MyFunc() { return; } } Index: test/SemaCXX/Inputs/malloc.h === --- test/SemaCXX/Inputs/malloc.h +++ test/SemaCXX/Inputs/malloc.h @@ -1,3 +1,5 @@ extern "C" { extern void *malloc (__SIZE_TYPE__ __size) throw () __attribute__ ((__malloc__)) ; + +void MyFunc() throw(); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D18652: [Inline asm] Correctly parse GCC-style asm line following MS-style asm line
d.zobnin.bugzilla added a reviewer: rsmith. d.zobnin.bugzilla removed a subscriber: rsmith. d.zobnin.bugzilla updated this revision to Diff 53543. d.zobnin.bugzilla added a comment. Richard, thank you for the review! I've created a static function to check if this is a GCC asm statement as you recommended to do, and also made "isTypeQualifier" function static. I've added a check for "goto" after "asm" to treat such statements as GCC-style assembly. Also, do you think it will be better to diagnose unsupported "asm goto" statements rather than fall into parsing them and emit "expected identifier" error or something like that? Thank you, Denis Zobnin http://reviews.llvm.org/D18652 Files: include/clang/Basic/DiagnosticParseKinds.td include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp lib/Parse/ParseStmtAsm.cpp test/CodeGen/inline-asm-mixed-style.c Index: lib/Parse/ParseStmtAsm.cpp === --- lib/Parse/ParseStmtAsm.cpp +++ lib/Parse/ParseStmtAsm.cpp @@ -335,6 +335,33 @@ return false; } +/// isTypeQualifier - Return true if the current token could be the +/// start of a type-qualifier-list. +static bool isTypeQualifier(const Token &Tok) { + switch (Tok.getKind()) { + default: return false; + // type-qualifier + case tok::kw_const: + case tok::kw_volatile: + case tok::kw_restrict: + case tok::kw___private: + case tok::kw___local: + case tok::kw___global: + case tok::kw___constant: + case tok::kw___generic: + case tok::kw___read_only: + case tok::kw___read_write: + case tok::kw___write_only: +return true; + } +} + +// Determine if this is a GCC-style asm statement. +static bool isGCCAsmStatement(const Token &TokAfterAsm) { + return TokAfterAsm.is(tok::l_paren) || TokAfterAsm.is(tok::kw_goto) || + isTypeQualifier(TokAfterAsm); +} + /// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled, /// this routine is called to collect the tokens for an MS asm statement. /// @@ -415,11 +442,11 @@ if (ExpLoc.first != FID || SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) { // If this is a single-line __asm, we're done, except if the next -// line begins with an __asm too, in which case we finish a comment +// line is MS-style asm too, in which case we finish a comment // if needed and then keep processing the next line as a single // line __asm. bool isAsm = Tok.is(tok::kw_asm); -if (SingleLineMode && !isAsm) +if (SingleLineMode && (!isAsm || isGCCAsmStatement(NextToken( break; // We're no longer in a comment. InAsmComment = false; @@ -643,8 +670,7 @@ assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); SourceLocation AsmLoc = ConsumeToken(); - if (getLangOpts().AsmBlocks && Tok.isNot(tok::l_paren) && - !isTypeQualifier()) { + if (getLangOpts().AsmBlocks && !isGCCAsmStatement(Tok)) { msAsm = true; return ParseMicrosoftAsmStatement(AsmLoc); } @@ -664,6 +690,14 @@ // Remember if this was a volatile asm. bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile; + + // TODO: support "asm goto" constructs (PR#9295). + if (Tok.is(tok::kw_goto)) { +Diag(Tok, diag::err_asm_goto_not_supported_yet); +SkipUntil(tok::r_paren, StopAtSemi); +return StmtError(); + } + if (Tok.isNot(tok::l_paren)) { Diag(Tok, diag::err_expected_lparen_after) << "asm"; SkipUntil(tok::r_paren, StopAtSemi); Index: lib/Parse/ParseDecl.cpp === --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -4259,27 +4259,6 @@ } } -/// isTypeSpecifierQualifier - Return true if the current token could be the -/// start of a type-qualifier-list. -bool Parser::isTypeQualifier() const { - switch (Tok.getKind()) { - default: return false; - // type-qualifier - case tok::kw_const: - case tok::kw_volatile: - case tok::kw_restrict: - case tok::kw___private: - case tok::kw___local: - case tok::kw___global: - case tok::kw___constant: - case tok::kw___generic: - case tok::kw___read_only: - case tok::kw___read_write: - case tok::kw___write_only: -return true; - } -} - /// isKnownToBeTypeSpecifier - Return true if we know that the specified token /// is definitely a type-specifier. Return false if it isn't part of a type /// specifier or if we're not sure. Index: include/clang/Parse/Parser.h === --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -1873,7 +1873,6 @@ bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false); bool isTypeSpecifierQualifier(); - bool isTypeQualifier() const; /// isKnownToBeTypeSpecifier - Return true if we know that the specified token /// is definitely a type-specifier. Return false if it isn't part of a type Index: i
Re: [PATCH] D18698: [C11] PR24451: Allow restrict _Atomic pointers
d.zobnin.bugzilla added a comment. Richard, please let me know what in your opinion we should do with this revision. Thank you, Denis Zobnin http://reviews.llvm.org/D18698 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D18700: [Inline asm][GCC compatibility] Handle %v-prefixed code in inline assembly
d.zobnin.bugzilla marked an inline comment as done. d.zobnin.bugzilla added a comment. Friendly ping, please take a look. Thank you, Denis Zobnin http://reviews.llvm.org/D18700 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D18657: Propagate missing empty exception spec from function declared in system header
d.zobnin.bugzilla added a comment. Friendly ping, please take a look. Thank you, Denis Zobnin http://reviews.llvm.org/D18657 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D18652: [Inline asm] Correctly parse GCC-style asm line following MS-style asm line
d.zobnin.bugzilla added a comment. Richard, Eric, Please take a look at the patch. Thank you, Denis Zobnin http://reviews.llvm.org/D18652 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r266976 - Correctly parse GCC-style asm line following MS-style asm line.
Author: dzobnin Date: Thu Apr 21 05:59:18 2016 New Revision: 266976 URL: http://llvm.org/viewvc/llvm-project?rev=266976&view=rev Log: Correctly parse GCC-style asm line following MS-style asm line. Quit parsing MS-style inline assembly if the following statement has GCC style. Enables compilation of code like void f() { __asm mov ebx, ecx __asm__("movl %ecx, %edx"); } Differential Revision: http://reviews.llvm.org/D18652 Added: cfe/trunk/test/CodeGen/inline-asm-mixed-style.c (with props) Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/lib/Parse/ParseDecl.cpp cfe/trunk/lib/Parse/ParseStmtAsm.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=266976&r1=266975&r2=266976&view=diff == --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu Apr 21 05:59:18 2016 @@ -27,6 +27,8 @@ def err_msasm_unable_to_create_target : "MS-style inline assembly is not available: %0">; def err_gnu_inline_asm_disabled : Error< "GNU-style inline assembly is disabled">; +def err_asm_goto_not_supported_yet : Error< + "'asm goto' constructs are not supported yet">; } let CategoryName = "Parse Issue" in { Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=266976&r1=266975&r2=266976&view=diff == --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Thu Apr 21 05:59:18 2016 @@ -1873,7 +1873,6 @@ private: bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false); bool isTypeSpecifierQualifier(); - bool isTypeQualifier() const; /// isKnownToBeTypeSpecifier - Return true if we know that the specified token /// is definitely a type-specifier. Return false if it isn't part of a type Modified: cfe/trunk/lib/Parse/ParseDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=266976&r1=266975&r2=266976&view=diff == --- cfe/trunk/lib/Parse/ParseDecl.cpp (original) +++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Apr 21 05:59:18 2016 @@ -4255,27 +4255,6 @@ void Parser::ParseEnumBody(SourceLocatio } } -/// isTypeSpecifierQualifier - Return true if the current token could be the -/// start of a type-qualifier-list. -bool Parser::isTypeQualifier() const { - switch (Tok.getKind()) { - default: return false; - // type-qualifier - case tok::kw_const: - case tok::kw_volatile: - case tok::kw_restrict: - case tok::kw___private: - case tok::kw___local: - case tok::kw___global: - case tok::kw___constant: - case tok::kw___generic: - case tok::kw___read_only: - case tok::kw___read_write: - case tok::kw___write_only: -return true; - } -} - /// isKnownToBeTypeSpecifier - Return true if we know that the specified token /// is definitely a type-specifier. Return false if it isn't part of a type /// specifier or if we're not sure. Modified: cfe/trunk/lib/Parse/ParseStmtAsm.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmtAsm.cpp?rev=266976&r1=266975&r2=266976&view=diff == --- cfe/trunk/lib/Parse/ParseStmtAsm.cpp (original) +++ cfe/trunk/lib/Parse/ParseStmtAsm.cpp Thu Apr 21 05:59:18 2016 @@ -335,6 +335,33 @@ static bool buildMSAsmString(Preprocesso return false; } +/// isTypeQualifier - Return true if the current token could be the +/// start of a type-qualifier-list. +static bool isTypeQualifier(const Token &Tok) { + switch (Tok.getKind()) { + default: return false; + // type-qualifier + case tok::kw_const: + case tok::kw_volatile: + case tok::kw_restrict: + case tok::kw___private: + case tok::kw___local: + case tok::kw___global: + case tok::kw___constant: + case tok::kw___generic: + case tok::kw___read_only: + case tok::kw___read_write: + case tok::kw___write_only: +return true; + } +} + +// Determine if this is a GCC-style asm statement. +static bool isGCCAsmStatement(const Token &TokAfterAsm) { + return TokAfterAsm.is(tok::l_paren) || TokAfterAsm.is(tok::kw_goto) || + isTypeQualifier(TokAfterAsm); +} + /// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled, /// this routine is called to collect the tokens for an MS asm statement. /// @@ -415,11 +442,11 @@ StmtResult Parser::ParseMicrosoftAsmStat if (ExpLoc.first != FID || SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) { // If this is a single-line __asm, we're done, except if the nex
[PATCH] D19361: [MS] Improved implementation of MS stack pragmas (vtordisp, *_seg)
d.zobnin.bugzilla created this revision. d.zobnin.bugzilla added a reviewer: rnk. d.zobnin.bugzilla added a subscriber: cfe-commits. This patch attempts to improve implementation of several MS pragmas that use stack (vtordisp, { bss | code | const | data }_seg) and fix some compatibility issues. Please take a look at the patch and let me know whether it's something worth working on and whether I'm on the right way of doing this. This patch: 1. Changes implementation of #pragma vtordisp to use existing PragmaStack<> template class that *_seg pragmas use; 2. Fixes "#pragma vtordisp()" reset behavior -- it shouldn't affect the stack; 3. Supports "save-and-restore" of pragma state stacks on entering / exiting a C++ method body, as MSVC does. If this work is accepted, I propose several to-do's: 1. Change #pragma pack implementation to use the same approach as other "stack" pragmas use; 2. Introduce diagnostics on popping named stack slots, as MSVC does Currently I tried to make Clang behave exactly as MSVC behaves, though, I can think of possible better solutions, please see "Implementation notes" below. Motivation: Currently Clang implements "stack" pragmas in several ways: "vtordisp" and "pack" have their own stacks in Sema, pragma actions are performed differently. MSVC seems to have a common implementation of all these pragmas. One common feature is "save-restore" on entering / exiting a C++ method body: ``` #pragma pack(4) #pragma pack(show) struct S { void f() { #pragma pack(push, 8) #pragma pack(show) } }; #pragma pack(show) ``` MSVC's output: 4, 8, 4 Clang's output: 4, 8, 8 MSVC seems to introduce artificial sentinel slots on entering a C++ method body and pops them on exit. Consider ``` #pragma pack(push, 4) struct S { void f() { #pragma pack(pop) } }; ``` MSVC emits: ``` warning C4159: #pragma vtordisp(pop,...): has popped previously pushed identifier '' ``` The same approach is used for "vtordisp" pragma, although it doesn't support #pragma vtordisp (pop, id) syntax. Please note that in the above example the stack gets corrupted and might lead to unexpected behavior later. I implemented "save-and-restore" feature for #pragma vtordisp in http://reviews.llvm.org/D14467 by copying a skack to a RAII object and back, no matter how many times "pop" is used. Pragmas other than "vtordisp" in Clang don't support this feature yet. Implementation notes: MSVC seems to use the same name "" even for methods of nested classes. It is legal in correct cases, because "#pragma (pop, id)" will look for the closest slot with mathing name, but if the nested sentinel slot is mistakenly popped, it will cause popping the stack up to surrounding sentinel. Maybe, if we choose this approach, we could use unique sentinel names for better recovery? Or even mark the sentinels to prevent a programmer from popping them by accident? http://reviews.llvm.org/D19361 Files: include/clang/Sema/Sema.h lib/Parse/ParsePragma.cpp lib/Parse/ParseStmt.cpp lib/Sema/Sema.cpp lib/Sema/SemaAttr.cpp test/CodeGenCXX/sections.cpp test/SemaCXX/pragma-vtordisp.cpp Index: lib/Parse/ParseStmt.cpp === --- lib/Parse/ParseStmt.cpp +++ lib/Parse/ParseStmt.cpp @@ -1928,7 +1928,8 @@ // Save and reset current vtordisp stack if we have entered a C++ method body. bool IsCXXMethod = getLangOpts().CPlusPlus && Decl && isa(Decl); - Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod); + Sema::PragmaStackSentinelRAII +PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod); // Do not enter a scope for the brace, as the arguments are in the same scope // (the function body) as the body itself. Instead, just read the statement @@ -1972,7 +1973,8 @@ // Save and reset current vtordisp stack if we have entered a C++ method body. bool IsCXXMethod = getLangOpts().CPlusPlus && Decl && isa(Decl); - Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod); + Sema::PragmaStackSentinelRAII +PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod); SourceLocation LBraceLoc = Tok.getLocation(); StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc, /*FnTry*/true)); Index: lib/Parse/ParsePragma.cpp === --- lib/Parse/ParsePragma.cpp +++ lib/Parse/ParsePragma.cpp @@ -497,11 +497,11 @@ void Parser::HandlePragmaMSVtorDisp() { assert(Tok.is(tok::annot_pragma_ms_vtordisp)); uintptr_t Value = reinterpret_cast(Tok.getAnnotationValue()); - Sema::PragmaVtorDispKind Kind = - static_cast((Value >> 16) & 0x); + Sema::PragmaMsStackAction Action = + static_cast((Value >> 16) & 0x); MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0x); SourceLocation PragmaLoc = ConsumeToken(); // The annotation token. - Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode); + Actions.A
r270686 - [ms][dll] #26935 Defining a dllimport function should cause it to be exported
Author: dzobnin Date: Wed May 25 06:32:42 2016 New Revision: 270686 URL: http://llvm.org/viewvc/llvm-project?rev=270686&view=rev Log: [ms][dll] #26935 Defining a dllimport function should cause it to be exported If we have some function with dllimport attribute and then we have the function definition in the same module but without dllimport attribute we should add dllexport attribute to this function definition. The same should be done for variables. Example: struct __declspec(dllimport) C3 { ~C3(); }; C3::~C3() {;} // we should export this definition. Patch by Andrew V. Tischenko Differential revision: http://reviews.llvm.org/D18953 Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/CodeGen/dllimport.c cfe/trunk/test/CodeGenCXX/dllimport-members.cpp cfe/trunk/test/CodeGenCXX/dllimport.cpp cfe/trunk/test/Sema/dllimport.c cfe/trunk/test/SemaCXX/dllimport.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=270686&r1=270685&r2=270686&view=diff == --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Wed May 25 06:32:42 2016 @@ -772,6 +772,7 @@ def MicrosoftEnumValue : DiagGroup<"micr def MicrosoftDefaultArgRedefinition : DiagGroup<"microsoft-default-arg-redefinition">; def MicrosoftTemplate : DiagGroup<"microsoft-template">; +def MicrosoftInconsistentDllImport : DiagGroup<"inconsistent-dllimport">; def MicrosoftRedeclareStatic : DiagGroup<"microsoft-redeclare-static">; def MicrosoftEnumForwardReference : DiagGroup<"microsoft-enum-forward-reference">; @@ -798,7 +799,8 @@ def Microsoft : DiagGroup<"microsoft", MicrosoftRedeclareStatic, MicrosoftEnumForwardReference, MicrosoftGoto, MicrosoftFlexibleArray, MicrosoftExtraQualification, MicrosoftCast, MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag, - MicrosoftCommentPaste, MicrosoftEndOfFile]>; + MicrosoftCommentPaste, MicrosoftEndOfFile, + MicrosoftInconsistentDllImport]>; def ClangClPch : DiagGroup<"clang-cl-pch">; Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=270686&r1=270685&r2=270686&view=diff == --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed May 25 06:32:42 2016 @@ -2359,7 +2359,10 @@ def err_attribute_aligned_too_great : Er "requested alignment must be %0 bytes or smaller">; def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< "%q0 redeclared without %1 attribute: previous %1 ignored">, - InGroup>; + InGroup; +def warn_redeclaration_without_import_attribute : Warning< + "%q0 redeclared without 'dllimport' attribute: 'dllexport' attribute added">, + InGroup; def warn_dllimport_dropped_from_inline_function : Warning< "%q0 redeclared inline; %1 attribute ignored">, InGroup; Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=270686&r1=270685&r2=270686&view=diff == --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed May 25 06:32:42 2016 @@ -5559,9 +5559,13 @@ static void checkAttributesAfterMerging( static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, NamedDecl *NewDecl, - bool IsSpecialization) { - if (TemplateDecl *OldTD = dyn_cast(OldDecl)) + bool IsSpecialization, + bool IsDefinition) { + if (TemplateDecl *OldTD = dyn_cast(OldDecl)) { OldDecl = OldTD->getTemplatedDecl(); +if (!IsSpecialization) + IsDefinition = false; + } if (TemplateDecl *NewTD = dyn_cast(NewDecl)) NewDecl = NewTD->getTemplatedDecl(); @@ -5617,14 +5621,17 @@ static void checkDLLAttributeRedeclarati // A redeclaration is not allowed to drop a dllimport attribute, the only // exceptions being inline function definitions, local extern declarations, - // and qualified friend declarations. - // NB: MSVC converts such a declaration to dllexport. + // qualified friend declarations or special MSVC extension: in the last case, + // the declaration is treated as if it were marked dllexport. bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false; - if (const auto *VD = dyn_cast(NewDecl)) + bool IsMicrosoft
[PATCH] D16112: PR26111: segmentation fault with __attribute__((mode(QI))) on function declaration
d.zobnin.bugzilla created this revision. d.zobnin.bugzilla added a reviewer: aaron.ballman. d.zobnin.bugzilla added a subscriber: cfe-commits. Allow "mode" attribute to be applied to VarDecl, not ValueDecl (which includes FunctionDecl and EnumConstantDecl), emit an error if this attribute is used with function declarations and enum constants. http://reviews.llvm.org/D16112 Files: include/clang/AST/Decl.h include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDeclAttr.cpp test/Sema/attr-mode.c Index: lib/Sema/SemaDeclAttr.cpp === --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -3372,11 +3372,11 @@ QualType OldTy; if (TypedefNameDecl *TD = dyn_cast(D)) OldTy = TD->getUnderlyingType(); - else if (ValueDecl *VD = dyn_cast(D)) + else if (VarDecl *VD = dyn_cast(D)) OldTy = VD->getType(); else { -S.Diag(D->getLocation(), diag::err_attr_wrong_decl) - << Attr.getName() << Attr.getRange(); +S.Diag(D->getLocation(), diag::err_mode_requires_typedef_or_variable) +<< Attr.getRange(); return; } @@ -3451,7 +3451,7 @@ if (TypedefNameDecl *TD = dyn_cast(D)) TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy); else -cast(D)->setType(NewTy); +cast(D)->setType(NewTy); D->addAttr(::new (S.Context) ModeAttr(Attr.getRange(), S.Context, Name, Index: include/clang/AST/Decl.h === --- include/clang/AST/Decl.h +++ include/clang/AST/Decl.h @@ -1954,6 +1954,7 @@ unsigned getMinRequiredArguments() const; QualType getReturnType() const { +assert(getType()->getAs() && "Expected a FunctionType!"); return getType()->getAs()->getReturnType(); } @@ -1964,6 +1965,7 @@ /// \brief Determine the type of an expression that calls this function. QualType getCallResultType() const { +assert(getType()->getAs() && "Expected a FunctionType!"); return getType()->getAs()->getCallResultType(getASTContext()); } Index: include/clang/Basic/DiagnosticSemaKinds.td === --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2838,14 +2838,14 @@ "mode attribute only supported for integer and floating-point types">; def err_mode_wrong_type : Error< "type of machine mode does not match type of base type">; +def err_mode_requires_typedef_or_variable : Error< + "mode attribute invalid on this declaration, requires typedef or variable">; def warn_vector_mode_deprecated : Warning< "specifying vector types with the 'mode' attribute is deprecated; " "use the 'vector_size' attribute instead">, InGroup; def err_complex_mode_vector_type : Error< "type of machine mode does not support base vector types">; -def err_attr_wrong_decl : Error< - "%0 attribute invalid on this declaration, requires typedef or value">; def warn_attribute_nonnull_no_pointers : Warning< "'nonnull' attribute applied to function with no pointer arguments">, InGroup; Index: test/Sema/attr-mode.c === --- test/Sema/attr-mode.c +++ test/Sema/attr-mode.c @@ -24,6 +24,9 @@ int **__attribute((mode(QI)))* i32; // expected-error{{mode attribute}} +__attribute__((mode(QI))) int invalid_func() { return 1; } // expected-error{{mode attribute invalid on this declaration}} +enum invalid_enum { A1 __attribute__((mode(QI))) }; // expected-error{{mode attribute invalid on this declaration}} + typedef _Complex double c32 __attribute((mode(SC))); int c32_test[sizeof(c32) == 8 ? 1 : -1]; typedef _Complex float c64 __attribute((mode(DC))); Index: lib/Sema/SemaDeclAttr.cpp === --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -3372,11 +3372,11 @@ QualType OldTy; if (TypedefNameDecl *TD = dyn_cast(D)) OldTy = TD->getUnderlyingType(); - else if (ValueDecl *VD = dyn_cast(D)) + else if (VarDecl *VD = dyn_cast(D)) OldTy = VD->getType(); else { -S.Diag(D->getLocation(), diag::err_attr_wrong_decl) - << Attr.getName() << Attr.getRange(); +S.Diag(D->getLocation(), diag::err_mode_requires_typedef_or_variable) +<< Attr.getRange(); return; } @@ -3451,7 +3451,7 @@ if (TypedefNameDecl *TD = dyn_cast(D)) TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy); else -cast(D)->setType(NewTy); +cast(D)->setType(NewTy); D->addAttr(::new (S.Context) ModeAttr(Attr.getRange(), S.Context, Name, Index: include/clang/AST/Decl.h === --- include/clang/AST/Decl.h +++ include/clang/AST/Decl.h @@ -1954,6 +1954,7 @@ unsigned getMinRequiredArguments() const; QualType getReturnType() const { +assert(getType()->getA
Re: [PATCH] D16112: PR26111: segmentation fault with __attribute__((mode(QI))) on function declaration
d.zobnin.bugzilla updated this revision to Diff 44859. d.zobnin.bugzilla added a comment. Thanks for the review! Updated the patch: added Subjects line for the attribute and removed the "err_attr_wrong_decl" diagnostics. http://reviews.llvm.org/D16112 Files: include/clang/AST/Decl.h include/clang/Basic/Attr.td include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDeclAttr.cpp test/Sema/attr-mode.c Index: lib/Sema/SemaDeclAttr.cpp === --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -3391,13 +3391,8 @@ QualType OldTy; if (TypedefNameDecl *TD = dyn_cast(D)) OldTy = TD->getUnderlyingType(); - else if (ValueDecl *VD = dyn_cast(D)) -OldTy = VD->getType(); - else { -S.Diag(D->getLocation(), diag::err_attr_wrong_decl) - << Attr.getName() << Attr.getRange(); -return; - } + else +OldTy = cast(D)->getType(); // Base type can also be a vector type (see PR17453). // Distinguish between base type and base element type. @@ -3470,7 +3465,7 @@ if (TypedefNameDecl *TD = dyn_cast(D)) TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy); else -cast(D)->setType(NewTy); +cast(D)->setType(NewTy); D->addAttr(::new (S.Context) ModeAttr(Attr.getRange(), S.Context, Name, Index: include/clang/AST/Decl.h === --- include/clang/AST/Decl.h +++ include/clang/AST/Decl.h @@ -1954,6 +1954,7 @@ unsigned getMinRequiredArguments() const; QualType getReturnType() const { +assert(getType()->getAs() && "Expected a FunctionType!"); return getType()->getAs()->getReturnType(); } @@ -1964,6 +1965,7 @@ /// \brief Determine the type of an expression that calls this function. QualType getCallResultType() const { +assert(getType()->getAs() && "Expected a FunctionType!"); return getType()->getAs()->getCallResultType(getASTContext()); } Index: include/clang/Basic/DiagnosticSemaKinds.td === --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2844,8 +2844,6 @@ InGroup; def err_complex_mode_vector_type : Error< "type of machine mode does not support base vector types">; -def err_attr_wrong_decl : Error< - "%0 attribute invalid on this declaration, requires typedef or value">; def warn_attribute_nonnull_no_pointers : Warning< "'nonnull' attribute applied to function with no pointer arguments">, InGroup; Index: include/clang/Basic/Attr.td === --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -878,6 +878,8 @@ def Mode : Attr { let Spellings = [GCC<"mode">]; + let Subjects = SubjectList<[Var, TypedefName], ErrorDiag, + "ExpectedVariableOrTypedef">; let Args = [IdentifierArgument<"Mode">]; let Documentation = [Undocumented]; } Index: test/Sema/attr-mode.c === --- test/Sema/attr-mode.c +++ test/Sema/attr-mode.c @@ -24,6 +24,9 @@ int **__attribute((mode(QI)))* i32; // expected-error{{mode attribute}} +__attribute__((mode(QI))) int invalid_func() { return 1; } // expected-error{{'mode' attribute only applies to variables and typedefs}} +enum invalid_enum { A1 __attribute__((mode(QI))) }; // expected-error{{'mode' attribute only applies to variables and typedefs}} + typedef _Complex double c32 __attribute((mode(SC))); int c32_test[sizeof(c32) == 8 ? 1 : -1]; typedef _Complex float c64 __attribute((mode(DC))); Index: lib/Sema/SemaDeclAttr.cpp === --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -3391,13 +3391,8 @@ QualType OldTy; if (TypedefNameDecl *TD = dyn_cast(D)) OldTy = TD->getUnderlyingType(); - else if (ValueDecl *VD = dyn_cast(D)) -OldTy = VD->getType(); - else { -S.Diag(D->getLocation(), diag::err_attr_wrong_decl) - << Attr.getName() << Attr.getRange(); -return; - } + else +OldTy = cast(D)->getType(); // Base type can also be a vector type (see PR17453). // Distinguish between base type and base element type. @@ -3470,7 +3465,7 @@ if (TypedefNameDecl *TD = dyn_cast(D)) TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy); else -cast(D)->setType(NewTy); +cast(D)->setType(NewTy); D->addAttr(::new (S.Context) ModeAttr(Attr.getRange(), S.Context, Name, Index: include/clang/AST/Decl.h === --- include/clang/AST/Decl.h +++ include/clang/AST/Decl.h @@ -1954,6 +1954,7 @@ unsigned getMinRequiredArguments() const; QualType getReturnType() const { +assert(getType()->getAs() && "Expected a FunctionType!"); return getType()-
[PATCH] D16216: Fix infinite loop when ::new or ::delete are found in member initializer list
d.zobnin.bugzilla created this revision. d.zobnin.bugzilla added reviewers: kcc, rsmith. d.zobnin.bugzilla added a subscriber: cfe-commits. Fix for a case found by fuzzing PR23057 (comment #33 https://llvm.org/bugs/show_bug.cgi?id=23057#c33). Diagnose and consume unexpected ::new and ::delete tokens to prevent infinite loop in parsing a member initializer list. http://reviews.llvm.org/D16216 Files: include/clang/Basic/DiagnosticParseKinds.td lib/Parse/ParseDeclCXX.cpp test/Parser/cxx-invalid-function-decl.cpp Index: lib/Parse/ParseDeclCXX.cpp === --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -3237,6 +3237,20 @@ CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); ParsedType TemplateTypeTy; + // If ::new or ::delete was met, ParseOptionalCXXScopeSpecifier just left + // them untouched. Diagnose it now to prevent infinite loop on parsing such + // code: "f() : ::new". + if (Tok.is(tok::coloncolon)) { +tok::TokenKind NextKind = NextToken().getKind(); +if (NextKind == tok::kw_new || NextKind == tok::kw_delete) { + SourceRange Range(Tok.getLocation(), NextToken().getEndLoc()); + Diag(Tok.getLocation(), diag::err_unexpected_in_member_initlist) + << (NextKind == tok::kw_delete) << Range; + ConsumeToken(); // the '::' token. + ConsumeToken(); // 'new' or 'delete'. + return true; +} + } if (Tok.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); if (TemplateId->Kind == TNK_Type_template || Index: include/clang/Basic/DiagnosticParseKinds.td === --- include/clang/Basic/DiagnosticParseKinds.td +++ include/clang/Basic/DiagnosticParseKinds.td @@ -161,6 +161,8 @@ def err_at_defs_cxx : Error<"@defs is not supported in Objective-C++">; def err_at_in_class : Error<"unexpected '@' in member specification">; def err_unexpected_semi : Error<"unexpected ';' before %0">; +def err_unexpected_in_member_initlist : Error< + "unexpected %select{'::new'|'::delete'}0 in member initializer list">; def err_expected_fn_body : Error< "expected function body after function declarator">; Index: test/Parser/cxx-invalid-function-decl.cpp === --- test/Parser/cxx-invalid-function-decl.cpp +++ test/Parser/cxx-invalid-function-decl.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f() : X() ::new{}; // expected-error{{missing ',' between base or member initializers}} +// expected-error@-1{{unexpected '::new' in member initializer list}} +// expected-error@-2{{only constructors take base initializers}} + +template +struct Base1 { + T x1; + Base1(T a1) : x1(a1) {} +}; + +template +struct Base2 { + T x2; + Base2(T a2) : x2(a2) {} +}; + +struct S : public Base1, public Base2 { + int x; + S() : ::Base1(0) ::new, ::Base2(1.0) ::delete x(2) {} // expected-error3{{missing ',' between base or member initializers}} +// expected-error@-1{{unexpected '::new' in member initializer list}} +// expected-error@-2{{unexpected '::delete' in member initializer list}} +}; Index: lib/Parse/ParseDeclCXX.cpp === --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -3237,6 +3237,20 @@ CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); ParsedType TemplateTypeTy; + // If ::new or ::delete was met, ParseOptionalCXXScopeSpecifier just left + // them untouched. Diagnose it now to prevent infinite loop on parsing such + // code: "f() : ::new". + if (Tok.is(tok::coloncolon)) { +tok::TokenKind NextKind = NextToken().getKind(); +if (NextKind == tok::kw_new || NextKind == tok::kw_delete) { + SourceRange Range(Tok.getLocation(), NextToken().getEndLoc()); + Diag(Tok.getLocation(), diag::err_unexpected_in_member_initlist) + << (NextKind == tok::kw_delete) << Range; + ConsumeToken(); // the '::' token. + ConsumeToken(); // 'new' or 'delete'. + return true; +} + } if (Tok.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); if (TemplateId->Kind == TNK_Type_template || Index: include/clang/Basic/DiagnosticParseKinds.td === --- include/clang/Basic/DiagnosticParseKinds.td +++ include/clang/Basic/DiagnosticParseKinds.td @@ -161,6 +161,8 @@ def err_at_defs_cxx : Error<"@defs is not supported in Objective-C++">; def err_at_in_class : Error<"unexpected '@' in member specification">; def err_un
[PATCH] D16219: PR8901: attribute "mode" rejected for enums and dependent types
d.zobnin.bugzilla created this revision. d.zobnin.bugzilla added a reviewer: aaron.ballman. d.zobnin.bugzilla added a subscriber: cfe-commits. Allow "mode" attribute for enum types, except for vector modes, for compatibility with GCC. Support "mode" attribute with dependent types. http://reviews.llvm.org/D16219 Files: include/clang/Basic/Attr.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/AttributeList.h include/clang/Sema/Sema.h lib/Sema/SemaDeclAttr.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CodeGen/attr-mode-enums.c test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp test/Sema/attr-mode-enums.c test/Sema/attr-mode.c test/SemaCXX/attr-mode-tmpl.cpp Index: lib/Sema/SemaTemplateInstantiateDecl.cpp === --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -227,6 +227,14 @@ Attr.getSpellingListIndex()); } +static void +instantiateDependentModeAttr(Sema &S, + const MultiLevelTemplateArgumentList &TemplateArgs, + const ModeAttr &Attr, Decl *New) { + S.AddModeAttr(Attr.getRange(), New, Attr.getMode(), +Attr.getSpellingListIndex(), /*InInstantiation=*/true); +} + void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -265,6 +273,11 @@ continue; } +if (const ModeAttr *Mode = dyn_cast(TmplAttr)) { + instantiateDependentModeAttr(*this, TemplateArgs, *Mode, New); + continue; +} + // Existing DLL attribute on the instantiation takes precedence. if (TmplAttr->getKind() == attr::DLLExport || TmplAttr->getKind() == attr::DLLImport) { Index: lib/Sema/SemaDeclAttr.cpp === --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -3293,6 +3293,8 @@ /// attribute. static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth, bool &IntegerMode, bool &ComplexMode) { + IntegerMode = true; + ComplexMode = false; switch (Str.size()) { case 2: switch (Str[0]) { @@ -3359,9 +3361,15 @@ } IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; - StringRef Str = Name->getName(); + S.AddModeAttr(Attr.getRange(), D, Name, Attr.getAttributeSpellingListIndex()); +} + +void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name, + unsigned SpellingListIndex, bool InInstantiation) { + StringRef Str = Name->getName(); normalizeName(Str); + SourceLocation AttrLoc = AttrRange.getBegin(); unsigned DestWidth = 0; bool IntegerMode = true; @@ -3377,99 +3385,126 @@ if (VectorStringLength && !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) && VectorSize.isPowerOf2()) { - parseModeAttrArg(S, Str.substr(VectorStringLength + 1), DestWidth, + parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth, IntegerMode, ComplexMode); - S.Diag(Attr.getLoc(), diag::warn_vector_mode_deprecated); + // Avoid duplicate warning from template instantiation. + if (!InInstantiation) +Diag(AttrLoc, diag::warn_vector_mode_deprecated); } else { VectorSize = 0; } } if (!VectorSize) -parseModeAttrArg(S, Str, DestWidth, IntegerMode, ComplexMode); +parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode); + + // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t + // and friends, at least with glibc. + // FIXME: Make sure floating-point mappings are accurate + // FIXME: Support XF and TF types + if (!DestWidth) { +Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name; +return; + } QualType OldTy; if (TypedefNameDecl *TD = dyn_cast(D)) OldTy = TD->getUnderlyingType(); - else + else if (EnumDecl *ED = dyn_cast(D)) { +// Something like 'typedef enum { X } __attribute__((mode(XX))) T;'. +// Try to get type from enum declaration, default to int. +OldTy = ED->getIntegerType(); +if (OldTy.isNull()) + OldTy = Context.IntTy; + } else OldTy = cast(D)->getType(); + if (OldTy->isDependentType()) { +D->addAttr(::new (Context) + ModeAttr(AttrRange, Context, Name, SpellingListIndex)); +return; + } + // Base type can also be a vector type (see PR17453). // Distinguish between base type and base element type. QualType OldElemTy = OldTy; if (const VectorType *VT = OldTy->getAs()) OldElemTy = VT->getElementType(); - if (!OldElemTy->getAs() && !OldElemTy->isComplexType()) -S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); + // GCC allows 'mode' attribute on enumeration types (even
Re: [PATCH] D13285: Fix for bug 24196: clang fails on assertion on complex doubles multiplication when EH is enabled
d.zobnin.bugzilla abandoned this revision. d.zobnin.bugzilla added a comment. This issue is fixed in http://reviews.llvm.org/rL253926. http://reviews.llvm.org/D13285 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D16216: Fix infinite loop when ::new or ::delete are found in member initializer list
d.zobnin.bugzilla updated this revision to Diff 45295. d.zobnin.bugzilla added a comment. Thank you for the review! Updated the patch: parser now skips the rest of the initializers if the previous one was invalid, added several checks to the test. http://reviews.llvm.org/D16216 Files: lib/Parse/ParseDeclCXX.cpp test/Parser/cxx-invalid-function-decl.cpp Index: lib/Parse/ParseDeclCXX.cpp === --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -3187,28 +3187,30 @@ Actions.CodeCompleteConstructorInitializer(ConstructorDecl, MemInitializers); return cutOffParsing(); -} else { - MemInitResult MemInit = ParseMemInitializer(ConstructorDecl); - if (!MemInit.isInvalid()) -MemInitializers.push_back(MemInit.get()); - else -AnyErrors = true; } - + +MemInitResult MemInit = ParseMemInitializer(ConstructorDecl); +if (!MemInit.isInvalid()) + MemInitializers.push_back(MemInit.get()); +else + AnyErrors = true; + if (Tok.is(tok::comma)) ConsumeToken(); else if (Tok.is(tok::l_brace)) break; -// If the next token looks like a base or member initializer, assume that -// we're just missing a comma. -else if (Tok.isOneOf(tok::identifier, tok::coloncolon)) { +// If the previous initializer was valid and the next token looks like a +// base or member initializer, assume that we're just missing a comma. +else if (!MemInit.isInvalid() && + Tok.isOneOf(tok::identifier, tok::coloncolon)) { SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation); Diag(Loc, diag::err_ctor_init_missing_comma) << FixItHint::CreateInsertion(Loc, ", "); } else { // Skip over garbage, until we get to '{'. Don't eat the '{'. - Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace - << tok::comma; + if (!MemInit.isInvalid()) +Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace + << tok::comma; SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch); break; } Index: test/Parser/cxx-invalid-function-decl.cpp === --- test/Parser/cxx-invalid-function-decl.cpp +++ test/Parser/cxx-invalid-function-decl.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Check that "::new" and "::delete" in member initializer list are diagnosed +// correctly and don't lead to infinite loop on parsing. + +// Error: X() (initializer on non-constructor), "::new" is skipped. +void f1() : X() ::new{}; // expected-error{{only constructors take base initializers}} + +// Errors: first "::delete" and initializer on non-constructor, others skipped. +void f2() : ::delete, ::new, X() ::new ::delete{} // expected-error{{expected class member or base class name}} + // expected-error@-1{{only constructors take base initializers}} + +// Errors: the '::' token, "::delete" and initializer on non-constructor, others skipped. +void f3() : ::, ::delete X(), ::new {}; // expected-error2{{expected class member or base class name}} +// expected-error@-1{{only constructors take base initializers}} + +template +struct Base1 { + T x1; + Base1(T a1) : x1(a1) {} +}; + +template +struct Base2 { + T x2; + Base2(T a2) : x2(a2) {} +}; + +struct S : public Base1, public Base2 { + int x; + + // 1-st initializer is correct (just missing ','), 2-nd incorrect, skip other. + S() : ::Base1(0) ::new, ::Base2(1.0) ::delete x(2) {} // expected-error{{expected class member or base class name}} +// expected-error@-1{{missing ',' between base or member initializers}} + + // 1-st and 2-nd are correct, errors: '::' and "::new", others skipped. + S(int a) : Base1(a), ::Base2(1.0), ::, // expected-error{{expected class member or base class name}} + ::new, ! ::delete, ::Base2<() x(3) {} // expected-error{{expected class member or base class name}} + + // All initializers are correct, nothing to skip, diagnose 2 missing commas. + S(const S &) : Base1(0) ::Base2(1.0) x(2) {} // expected-error2{{missing ',' between base or member initializers}} +}; Index: lib/Parse/ParseDeclCXX.cpp === --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -3187,28 +3187,30 @@ Actions.CodeCompleteConstructorInitializer(ConstructorDecl, MemInitializers); return cutOffParsing(); -} else { - MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
Re: [PATCH] D16216: Fix infinite loop when ::new or ::delete are found in member initializer list
d.zobnin.bugzilla added a subscriber: ABataev. d.zobnin.bugzilla added a comment. I am going to ask @ABataev to commit this. Hope to get commit access soon (this is my 5th patch) :) http://reviews.llvm.org/D16216 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D16219: PR8901: attribute "mode" rejected for enums and dependent types
d.zobnin.bugzilla updated this revision to Diff 45401. d.zobnin.bugzilla added a comment. Updated the patch after committed fix for http://reviews.llvm.org/D16301 (r258213). This patch: 1. Adds "Enum" Subject to 'mode' attribute to be able to compile code like "typedef enum { X } __attribute__((mode(QI))) T;" 2. Moves handling of the attribute to a new Sema's method in order to support 'mode' attribute on dependent types; 3. Adds several cases to the tests (both for templates and non-dependent types). Please take a look. http://reviews.llvm.org/D16219 Files: include/clang/Basic/Attr.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/AttributeList.h include/clang/Sema/Sema.h lib/Sema/SemaDeclAttr.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CodeGen/attr-mode-enums.c test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp test/Sema/attr-mode-enums.c test/Sema/attr-mode.c test/SemaCXX/attr-mode-tmpl.cpp Index: lib/Sema/SemaTemplateInstantiateDecl.cpp === --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -227,6 +227,14 @@ Attr.getSpellingListIndex()); } +static void +instantiateDependentModeAttr(Sema &S, + const MultiLevelTemplateArgumentList &TemplateArgs, + const ModeAttr &Attr, Decl *New) { + S.AddModeAttr(Attr.getRange(), New, Attr.getMode(), +Attr.getSpellingListIndex(), /*InInstantiation=*/true); +} + void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -265,6 +273,11 @@ continue; } +if (const ModeAttr *Mode = dyn_cast(TmplAttr)) { + instantiateDependentModeAttr(*this, TemplateArgs, *Mode, New); + continue; +} + // Existing DLL attribute on the instantiation takes precedence. if (TmplAttr->getKind() == attr::DLLExport || TmplAttr->getKind() == attr::DLLImport) { Index: lib/Sema/SemaDeclAttr.cpp === --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -3293,6 +3293,8 @@ /// attribute. static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth, bool &IntegerMode, bool &ComplexMode) { + IntegerMode = true; + ComplexMode = false; switch (Str.size()) { case 2: switch (Str[0]) { @@ -3359,9 +3361,15 @@ } IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; - StringRef Str = Name->getName(); + S.AddModeAttr(Attr.getRange(), D, Name, Attr.getAttributeSpellingListIndex()); +} + +void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name, + unsigned SpellingListIndex, bool InInstantiation) { + StringRef Str = Name->getName(); normalizeName(Str); + SourceLocation AttrLoc = AttrRange.getBegin(); unsigned DestWidth = 0; bool IntegerMode = true; @@ -3377,99 +3385,126 @@ if (VectorStringLength && !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) && VectorSize.isPowerOf2()) { - parseModeAttrArg(S, Str.substr(VectorStringLength + 1), DestWidth, + parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth, IntegerMode, ComplexMode); - S.Diag(Attr.getLoc(), diag::warn_vector_mode_deprecated); + // Avoid duplicate warning from template instantiation. + if (!InInstantiation) +Diag(AttrLoc, diag::warn_vector_mode_deprecated); } else { VectorSize = 0; } } if (!VectorSize) -parseModeAttrArg(S, Str, DestWidth, IntegerMode, ComplexMode); +parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode); + + // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t + // and friends, at least with glibc. + // FIXME: Make sure floating-point mappings are accurate + // FIXME: Support XF and TF types + if (!DestWidth) { +Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name; +return; + } QualType OldTy; if (TypedefNameDecl *TD = dyn_cast(D)) OldTy = TD->getUnderlyingType(); - else + else if (EnumDecl *ED = dyn_cast(D)) { +// Something like 'typedef enum { X } __attribute__((mode(XX))) T;'. +// Try to get type from enum declaration, default to int. +OldTy = ED->getIntegerType(); +if (OldTy.isNull()) + OldTy = Context.IntTy; + } else OldTy = cast(D)->getType(); + if (OldTy->isDependentType()) { +D->addAttr(::new (Context) + ModeAttr(AttrRange, Context, Name, SpellingListIndex)); +return; + } + // Base type can also be a vector type (see PR17453). // Distinguish between base type and base element type. QualType OldElemTy = OldTy; if (const V
Re: [PATCH] D16219: PR8901: attribute "mode" rejected for enums and dependent types
d.zobnin.bugzilla added a comment. Friendly ping, please take a look. http://reviews.llvm.org/D16219 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D16630: PR23057: Fix assertion `Val && "isa<> used on a null pointer"' on invalid for-range expression
d.zobnin.bugzilla created this revision. d.zobnin.bugzilla added reviewers: kcc, rsmith. d.zobnin.bugzilla added a subscriber: cfe-commits. Fix the issue discovered by fuzzing (https://llvm.org/bugs/show_bug.cgi?id=23057#c18) by handling nullptr in Sema::ActOnCXXForRangeDecl and correct delayed typos in for-range expression before calling Sema::ActOnCXXForRangeStmt (fixes PR26288 as well). http://reviews.llvm.org/D16630 Files: lib/Parse/ParseStmt.cpp lib/Sema/SemaDecl.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp test/Parser/cxx-invalid-for-range.cpp Index: lib/Parse/ParseStmt.cpp === --- lib/Parse/ParseStmt.cpp +++ lib/Parse/ParseStmt.cpp @@ -1716,9 +1716,11 @@ StmtResult ForEachStmt; if (ForRange) { +ExprResult CorrectedRange = +Actions.CorrectDelayedTyposInExpr(ForRangeInit.RangeExpr.get()); ForRangeStmt = Actions.ActOnCXXForRangeStmt( getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(), -ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(), +ForRangeInit.ColonLoc, CorrectedRange.get(), T.getCloseLocation(), Sema::BFRK_Build); // Similarly, we need to do the semantic analysis for a for-range Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -9901,6 +9901,10 @@ } void Sema::ActOnCXXForRangeDecl(Decl *D) { + // If there is no declaration, there was an error parsing it. Ignore it. + if (!D) +return; + VarDecl *VD = dyn_cast(D); if (!VD) { Diag(D->getLocation(), diag::err_for_range_decl_must_be_var); Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp === --- test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp +++ test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp @@ -18,6 +18,9 @@ for (struct S { S(int) {} } s : arr) { // expected-error {{types may not be defined in a for range declaration}} } + for (struct S { S(int) {} } s : Undeclared); // expected-error{{types may not be defined in a for range declaration}} + // expected-error@-1{{use of undeclared identifier 'Undeclared'}} + new struct T {}; // expected-error {{'T' cannot be defined in a type specifier}} new struct A {}; // expected-error {{'A' cannot be defined in a type specifier}} Index: test/Parser/cxx-invalid-for-range.cpp === --- test/Parser/cxx-invalid-for-range.cpp +++ test/Parser/cxx-invalid-for-range.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// From PR23057 comment #18 (https://llvm.org/bugs/show_bug.cgi?id=23057#c18). + +namespace N { + int X[10]; // expected-note{{declared here +} + +void f1() { + for (auto operator new : X); // expected-error{{'operator new' cannot be the name of a variable or data member}} + // expected-error@-1{{use of undeclared identifier 'X'; did you mean 'N::X'?}} +} + +void f2() { + for (a operator== :) // expected-error{{'operator==' cannot be the name of a variable or data member}} + // expected-error@-1{{expected expression}} + // expected-error@-2{{unknown type name 'a'}} +} // expected-error{{expected statement}} Index: lib/Parse/ParseStmt.cpp === --- lib/Parse/ParseStmt.cpp +++ lib/Parse/ParseStmt.cpp @@ -1716,9 +1716,11 @@ StmtResult ForEachStmt; if (ForRange) { +ExprResult CorrectedRange = +Actions.CorrectDelayedTyposInExpr(ForRangeInit.RangeExpr.get()); ForRangeStmt = Actions.ActOnCXXForRangeStmt( getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(), -ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(), +ForRangeInit.ColonLoc, CorrectedRange.get(), T.getCloseLocation(), Sema::BFRK_Build); // Similarly, we need to do the semantic analysis for a for-range Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -9901,6 +9901,10 @@ } void Sema::ActOnCXXForRangeDecl(Decl *D) { + // If there is no declaration, there was an error parsing it. Ignore it. + if (!D) +return; + VarDecl *VD = dyn_cast(D); if (!VD) { Diag(D->getLocation(), diag::err_for_range_decl_must_be_var); Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp === --- test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp +++ test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp @@ -18,6 +18,9 @@ for (struct S { S(int) {} } s : arr) { // expected-error {{types may not be defined in a for range declaration}} } + for (struct S { S(int) {} } s : Undeclared); // expected-error{{types may not be define
Re: [PATCH] D14467: [MS] Fix for bug 25013 - #pragma vtordisp is unknown inside functions.
d.zobnin.bugzilla updated this revision to Diff 40380. d.zobnin.bugzilla added a comment. Only tests have been updated: enabled a test case for Sema, which pass with these changes, added corresponding test case for CodeGen. http://reviews.llvm.org/D14467 Files: include/clang/Sema/Sema.h lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseStmt.cpp test/Layout/ms-vtordisp-local.cpp test/SemaCXX/pragma-vtordisp.cpp Index: lib/Parse/ParseDeclCXX.cpp === --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -2854,6 +2854,11 @@ return DeclGroupPtrTy(); } + if (Tok.is(tok::annot_pragma_ms_vtordisp)) { +HandlePragmaMSVtorDisp(); +return DeclGroupPtrTy(); + } + // If we see a namespace here, a close brace was missing somewhere. if (Tok.is(tok::kw_namespace)) { DiagnoseUnexpectedNamespace(cast(TagDecl)); Index: lib/Parse/ParseStmt.cpp === --- lib/Parse/ParseStmt.cpp +++ lib/Parse/ParseStmt.cpp @@ -358,6 +358,11 @@ HandlePragmaMSPragma(); return StmtEmpty(); + case tok::annot_pragma_ms_vtordisp: +ProhibitAttributes(Attrs); +HandlePragmaMSVtorDisp(); +return StmtEmpty(); + case tok::annot_pragma_loop_hint: ProhibitAttributes(Attrs); return ParsePragmaLoopHint(Stmts, OnlyStatement, TrailingElseLoc, Attrs); @@ -885,6 +890,9 @@ case tok::annot_pragma_ms_pragma: HandlePragmaMSPragma(); break; +case tok::annot_pragma_ms_vtordisp: + HandlePragmaMSVtorDisp(); + break; default: checkForPragmas = false; break; @@ -1895,6 +1903,11 @@ PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc, "parsing function body"); + // Save and reset current vtordisp stack if we have entered a C++ method body. + bool IsCXXMethod = + getLangOpts().CPlusPlus && Decl && isa(Decl); + Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod); + // Do not enter a scope for the brace, as the arguments are in the same scope // (the function body) as the body itself. Instead, just read the statement // list and put it into a CompoundStmt for safe keeping. @@ -1934,6 +1947,11 @@ return Actions.ActOnSkippedFunctionBody(Decl); } + // Save and reset current vtordisp stack if we have entered a C++ method body. + bool IsCXXMethod = + getLangOpts().CPlusPlus && Decl && isa(Decl); + Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod); + SourceLocation LBraceLoc = Tok.getLocation(); StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc, /*FnTry*/true)); // If we failed to parse the try-catch, we just give the function an empty Index: include/clang/Sema/Sema.h === --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -1007,6 +1007,24 @@ bool OldFPContractState : 1; }; + /// Records and restores the vtordisp state on entry/exit of C++ method body. + class VtorDispStackRAII { + public: +VtorDispStackRAII(Sema &S, bool ShouldSaveAndRestore) + : S(S), ShouldSaveAndRestore(ShouldSaveAndRestore), OldVtorDispStack() { + if (ShouldSaveAndRestore) +OldVtorDispStack = S.VtorDispModeStack; +} +~VtorDispStackRAII() { + if (ShouldSaveAndRestore) +S.VtorDispModeStack = OldVtorDispStack; +} + private: +Sema &S; +bool ShouldSaveAndRestore; +SmallVector OldVtorDispStack; + }; + void addImplicitTypedef(StringRef Name, QualType T); public: Index: test/Layout/ms-vtordisp-local.cpp === --- test/Layout/ms-vtordisp-local.cpp +++ test/Layout/ms-vtordisp-local.cpp @@ -0,0 +1,217 @@ +// RUN: %clang_cc1 -fms-extensions -fexceptions -fcxx-exceptions -emit-llvm-only -triple x86_64-pc-win32 -fdump-record-layouts -fsyntax-only %s 2>&1 | FileCheck %s + +struct Base { + virtual ~Base() {} + virtual void BaseFunc() {} +}; + +#pragma vtordisp(0) + +struct Container { + static void f() try { +#pragma vtordisp(2) +struct HasVtorDisp : virtual Base { + virtual ~HasVtorDisp() {} + virtual void Func() {} +}; + +int x[sizeof(HasVtorDisp)]; + +// HasVtorDisp: vtordisp because of pragma right before it. +// +// CHECK: *** Dumping AST Record Layout +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct HasVtorDisp +// CHECK-NEXT: 0 | (HasVtorDisp vftable pointer) +// CHECK-NEXT: 8 | (HasVtorDisp vbtable pointer) +// CHECK-NEXT: 20 | (vtordisp for vbase Base) +// CHECK-NEXT: 24 | struct Base (virtual base) +// CHECK-NEXT: 24 | (Base vftable pointer) +// CHECK-NEXT:| [sizeof=32, align=8, +// CHECK-NEXT:| nvsize=16, nvalign=8] + } catch (...) { + } +};
Re: [PATCH] D14467: [MS] Fix for bug 25013 - #pragma vtordisp is unknown inside functions.
d.zobnin.bugzilla added inline comments. Comment at: test/SemaCXX/pragma-vtordisp.cpp:34-35 @@ -33,6 +33,4 @@ struct C { -// FIXME: Our implementation based on token insertion makes it impossible for -// the pragma to appear everywhere we should support it. -//#pragma vtordisp() +#pragma vtordisp() struct D : virtual A { Yes, we can. Enabled this case, it passes with these changes. http://reviews.llvm.org/D14467 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits