head	1.1;
branch	1.1.1;
access;
symbols
	netbsd-11-0-RC4:1.1.1.11
	netbsd-11-0-RC3:1.1.1.11
	netbsd-11-0-RC2:1.1.1.11
	netbsd-11-0-RC1:1.1.1.11
	perseant-exfatfs-base-20250801:1.1.1.11
	netbsd-11:1.1.1.11.0.10
	netbsd-11-base:1.1.1.11
	netbsd-10-1-RELEASE:1.1.1.11
	perseant-exfatfs-base-20240630:1.1.1.11
	perseant-exfatfs:1.1.1.11.0.8
	perseant-exfatfs-base:1.1.1.11
	netbsd-8-3-RELEASE:1.1.1.8
	netbsd-9-4-RELEASE:1.1.1.10
	netbsd-10-0-RELEASE:1.1.1.11
	netbsd-10-0-RC6:1.1.1.11
	netbsd-10-0-RC5:1.1.1.11
	netbsd-10-0-RC4:1.1.1.11
	netbsd-10-0-RC3:1.1.1.11
	netbsd-10-0-RC2:1.1.1.11
	netbsd-10-0-RC1:1.1.1.11
	netbsd-10:1.1.1.11.0.6
	netbsd-10-base:1.1.1.11
	netbsd-9-3-RELEASE:1.1.1.10
	cjep_sun2x:1.1.1.11.0.4
	cjep_sun2x-base:1.1.1.11
	cjep_staticlib_x-base1:1.1.1.11
	netbsd-9-2-RELEASE:1.1.1.10
	cjep_staticlib_x:1.1.1.11.0.2
	cjep_staticlib_x-base:1.1.1.11
	netbsd-9-1-RELEASE:1.1.1.10
	phil-wifi-20200421:1.1.1.11
	phil-wifi-20200411:1.1.1.11
	phil-wifi-20200406:1.1.1.11
	netbsd-8-2-RELEASE:1.1.1.8
	netbsd-9-0-RELEASE:1.1.1.10
	netbsd-9-0-RC2:1.1.1.10
	netbsd-9-0-RC1:1.1.1.10
	netbsd-9:1.1.1.10.0.2
	netbsd-9-base:1.1.1.10
	phil-wifi-20190609:1.1.1.10
	netbsd-8-1-RELEASE:1.1.1.8
	netbsd-8-1-RC1:1.1.1.8
	pgoyette-compat-merge-20190127:1.1.1.9.2.1
	pgoyette-compat-20190127:1.1.1.10
	pgoyette-compat-20190118:1.1.1.10
	pgoyette-compat-1226:1.1.1.10
	pgoyette-compat-1126:1.1.1.10
	pgoyette-compat-1020:1.1.1.10
	pgoyette-compat-0930:1.1.1.10
	pgoyette-compat-0906:1.1.1.10
	netbsd-7-2-RELEASE:1.1.1.5.2.1
	pgoyette-compat-0728:1.1.1.10
	clang-337282:1.1.1.10
	netbsd-8-0-RELEASE:1.1.1.8
	phil-wifi:1.1.1.9.0.4
	phil-wifi-base:1.1.1.9
	pgoyette-compat-0625:1.1.1.9
	netbsd-8-0-RC2:1.1.1.8
	pgoyette-compat-0521:1.1.1.9
	pgoyette-compat-0502:1.1.1.9
	pgoyette-compat-0422:1.1.1.9
	netbsd-8-0-RC1:1.1.1.8
	pgoyette-compat-0415:1.1.1.9
	pgoyette-compat-0407:1.1.1.9
	pgoyette-compat-0330:1.1.1.9
	pgoyette-compat-0322:1.1.1.9
	pgoyette-compat-0315:1.1.1.9
	netbsd-7-1-2-RELEASE:1.1.1.5.2.1
	pgoyette-compat:1.1.1.9.0.2
	pgoyette-compat-base:1.1.1.9
	netbsd-7-1-1-RELEASE:1.1.1.5.2.1
	clang-319952:1.1.1.9
	matt-nb8-mediatek:1.1.1.8.0.10
	matt-nb8-mediatek-base:1.1.1.8
	clang-309604:1.1.1.9
	perseant-stdc-iso10646:1.1.1.8.0.8
	perseant-stdc-iso10646-base:1.1.1.8
	netbsd-8:1.1.1.8.0.6
	netbsd-8-base:1.1.1.8
	prg-localcount2-base3:1.1.1.8
	prg-localcount2-base2:1.1.1.8
	prg-localcount2-base1:1.1.1.8
	prg-localcount2:1.1.1.8.0.4
	prg-localcount2-base:1.1.1.8
	pgoyette-localcount-20170426:1.1.1.8
	bouyer-socketcan-base1:1.1.1.8
	pgoyette-localcount-20170320:1.1.1.8
	netbsd-7-1:1.1.1.5.2.1.0.6
	netbsd-7-1-RELEASE:1.1.1.5.2.1
	netbsd-7-1-RC2:1.1.1.5.2.1
	clang-294123:1.1.1.8
	netbsd-7-nhusb-base-20170116:1.1.1.5.2.1
	bouyer-socketcan:1.1.1.8.0.2
	bouyer-socketcan-base:1.1.1.8
	clang-291444:1.1.1.8
	pgoyette-localcount-20170107:1.1.1.7
	netbsd-7-1-RC1:1.1.1.5.2.1
	pgoyette-localcount-20161104:1.1.1.7
	netbsd-7-0-2-RELEASE:1.1.1.5.2.1
	localcount-20160914:1.1.1.7
	netbsd-7-nhusb:1.1.1.5.2.1.0.4
	netbsd-7-nhusb-base:1.1.1.5.2.1
	clang-280599:1.1.1.7
	pgoyette-localcount-20160806:1.1.1.7
	pgoyette-localcount-20160726:1.1.1.7
	pgoyette-localcount:1.1.1.7.0.2
	pgoyette-localcount-base:1.1.1.7
	netbsd-7-0-1-RELEASE:1.1.1.5.2.1
	clang-261930:1.1.1.7
	netbsd-7-0:1.1.1.5.2.1.0.2
	netbsd-7-0-RELEASE:1.1.1.5.2.1
	netbsd-7-0-RC3:1.1.1.5.2.1
	netbsd-7-0-RC2:1.1.1.5.2.1
	netbsd-7-0-RC1:1.1.1.5.2.1
	clang-237755:1.1.1.6
	clang-232565:1.1.1.6
	clang-227398:1.1.1.6
	tls-maxphys-base:1.1.1.5
	tls-maxphys:1.1.1.5.0.4
	netbsd-7:1.1.1.5.0.2
	netbsd-7-base:1.1.1.5
	clang-215315:1.1.1.5
	clang-209886:1.1.1.4
	yamt-pagecache:1.1.1.3.0.4
	yamt-pagecache-base9:1.1.1.3
	tls-earlyentropy:1.1.1.3.0.2
	tls-earlyentropy-base:1.1.1.4
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1.1.3
	riastradh-drm2-base3:1.1.1.3
	clang-202566:1.1.1.3
	clang-201163:1.1.1.3
	clang-199312:1.1.1.2
	clang-198450:1.1.1.1
	clang-196603:1.1.1.1
	clang-195771:1.1.1.1
	LLVM:1.1.1;
locks; strict;
comment	@// @;


1.1
date	2013.11.28.14.14.50;	author joerg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	ow8OybrawrB1f3fx;

1.1.1.1
date	2013.11.28.14.14.50;	author joerg;	state Exp;
branches;
next	1.1.1.2;
commitid	ow8OybrawrB1f3fx;

1.1.1.2
date	2014.01.15.21.26.21;	author joerg;	state Exp;
branches;
next	1.1.1.3;
commitid	NQXlzzA0SPkc5glx;

1.1.1.3
date	2014.02.14.20.07.14;	author joerg;	state Exp;
branches
	1.1.1.3.2.1
	1.1.1.3.4.1;
next	1.1.1.4;
commitid	annVkZ1sc17rF6px;

1.1.1.4
date	2014.05.30.18.14.42;	author joerg;	state Exp;
branches;
next	1.1.1.5;
commitid	8q0kdlBlCn09GACx;

1.1.1.5
date	2014.08.10.17.08.29;	author joerg;	state Exp;
branches
	1.1.1.5.2.1
	1.1.1.5.4.1;
next	1.1.1.6;
commitid	N85tXAN6Ex9VZPLx;

1.1.1.6
date	2015.01.29.19.57.28;	author joerg;	state Exp;
branches;
next	1.1.1.7;
commitid	mlISSizlPKvepX7y;

1.1.1.7
date	2016.02.27.22.12.00;	author joerg;	state Exp;
branches
	1.1.1.7.2.1;
next	1.1.1.8;
commitid	tIimz3oDlh1NpBWy;

1.1.1.8
date	2017.01.11.10.34.27;	author joerg;	state Exp;
branches;
next	1.1.1.9;
commitid	CNnUNfII1jgNmxBz;

1.1.1.9
date	2017.08.01.19.35.02;	author joerg;	state Exp;
branches
	1.1.1.9.2.1
	1.1.1.9.4.1;
next	1.1.1.10;
commitid	pMuDy65V0VicSx1A;

1.1.1.10
date	2018.07.17.18.31.24;	author joerg;	state Exp;
branches;
next	1.1.1.11;
commitid	wDzL46ALjrCZgwKA;

1.1.1.11
date	2019.11.13.22.19.27;	author joerg;	state dead;
branches;
next	;
commitid	QD8YATxuNG34YJKB;

1.1.1.3.2.1
date	2014.08.10.07.08.09;	author tls;	state Exp;
branches;
next	;
commitid	t01A1TLTYxkpGMLx;

1.1.1.3.4.1
date	2014.02.14.20.07.14;	author yamt;	state dead;
branches;
next	1.1.1.3.4.2;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.3.4.2
date	2014.05.22.16.18.30;	author yamt;	state Exp;
branches;
next	;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.5.2.1
date	2015.06.04.20.04.30;	author snj;	state Exp;
branches;
next	;
commitid	yRnjq9fueSo6n9oy;

1.1.1.5.4.1
date	2014.08.10.17.08.29;	author tls;	state dead;
branches;
next	1.1.1.5.4.2;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.5.4.2
date	2014.08.19.23.47.30;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.7.2.1
date	2017.03.20.06.52.41;	author pgoyette;	state Exp;
branches;
next	;
commitid	jjw7cAwgyKq7RfKz;

1.1.1.9.2.1
date	2018.07.28.04.33.22;	author pgoyette;	state Exp;
branches;
next	;
commitid	1UP1xAIUxv1ZgRLA;

1.1.1.9.4.1
date	2019.06.10.21.45.27;	author christos;	state Exp;
branches;
next	1.1.1.9.4.2;
commitid	jtc8rnCzWiEEHGqB;

1.1.1.9.4.2
date	2020.04.13.07.46.37;	author martin;	state dead;
branches;
next	;
commitid	X01YhRUPVUDaec4C;


desc
@@


1.1
log
@Initial revision
@
text
@//===--- SemaStmtAttr.cpp - Statement Attribute Handling ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements stmt-related attribute processing.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaInternal.h"
#include "TargetAttributesSema.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/StringExtras.h"

using namespace clang;
using namespace sema;

static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
                                   SourceRange Range) {
  if (!isa<NullStmt>(St)) {
    S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target)
        << St->getLocStart();
    if (isa<SwitchCase>(St)) {
      SourceLocation L = Lexer::getLocForEndOfToken(Range.getEnd(), 0,
                                  S.getSourceManager(), S.getLangOpts());
      S.Diag(L, diag::note_fallthrough_insert_semi_fixit)
          << FixItHint::CreateInsertion(L, ";");
    }
    return 0;
  }
  if (S.getCurFunction()->SwitchStack.empty()) {
    S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_outside_switch);
    return 0;
  }
  return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context);
}


static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
                                  SourceRange Range) {
  switch (A.getKind()) {
  case AttributeList::UnknownAttribute:
    S.Diag(A.getLoc(), A.isDeclspecAttribute() ?
           diag::warn_unhandled_ms_attribute_ignored :
           diag::warn_unknown_attribute_ignored) << A.getName();
    return 0;
  case AttributeList::AT_FallThrough:
    return handleFallThroughAttr(S, St, A, Range);
  default:
    // if we're here, then we parsed a known attribute, but didn't recognize
    // it as a statement attribute => it is declaration attribute
    S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt)
        << A.getName() << St->getLocStart();
    return 0;
  }
}

StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
                                       SourceRange Range) {
  SmallVector<const Attr*, 8> Attrs;
  for (const AttributeList* l = AttrList; l; l = l->getNext()) {
    if (Attr *a = ProcessStmtAttribute(*this, S, *l, Range))
      Attrs.push_back(a);
  }

  if (Attrs.empty())
    return S;

  return ActOnAttributedStmt(Range.getBegin(), Attrs, S);
}
@


1.1.1.1
log
@Import Clang 3.4rc1 r195771.
@
text
@@


1.1.1.2
log
@Import Clang 3.5svn r199312
@
text
@d15 1
@


1.1.1.3
log
@Import Clang 3.5svn r201163.
@
text
@d43 1
a43 2
  return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context,
                                           A.getAttributeSpellingListIndex());
@


1.1.1.3.2.1
log
@Rebase.
@
text
@d17 1
d32 2
a33 1
      SourceLocation L = S.getLocForEndOfToken(Range.getEnd());
d37 1
a37 1
    return nullptr;
d41 1
a41 1
    return nullptr;
d55 1
a55 1
    return nullptr;
d63 1
a63 1
    return nullptr;
@


1.1.1.4
log
@Import Clang 3.5svn r209886.
@
text
@d17 1
d32 2
a33 1
      SourceLocation L = S.getLocForEndOfToken(Range.getEnd());
d37 1
a37 1
    return nullptr;
d41 1
a41 1
    return nullptr;
d55 1
a55 1
    return nullptr;
d63 1
a63 1
    return nullptr;
@


1.1.1.5
log
@Import clang 3.6svn r215315.
@
text
@a18 1
#include "clang/Sema/LoopHint.h"
a44 152
static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
                                SourceRange) {
  IdentifierLoc *PragmaNameLoc = A.getArgAsIdent(0);
  IdentifierLoc *OptionLoc = A.getArgAsIdent(1);
  IdentifierLoc *StateLoc = A.getArgAsIdent(2);
  Expr *ValueExpr = A.getArgAsExpr(3);

  bool PragmaUnroll = PragmaNameLoc->Ident->getName() == "unroll";
  bool PragmaNoUnroll = PragmaNameLoc->Ident->getName() == "nounroll";
  if (St->getStmtClass() != Stmt::DoStmtClass &&
      St->getStmtClass() != Stmt::ForStmtClass &&
      St->getStmtClass() != Stmt::CXXForRangeStmtClass &&
      St->getStmtClass() != Stmt::WhileStmtClass) {
    const char *Pragma =
        llvm::StringSwitch<const char *>(PragmaNameLoc->Ident->getName())
            .Case("unroll", "#pragma unroll")
            .Case("nounroll", "#pragma nounroll")
            .Default("#pragma clang loop");
    S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
    return nullptr;
  }

  LoopHintAttr::OptionType Option;
  LoopHintAttr::Spelling Spelling;
  if (PragmaUnroll) {
    Option = ValueExpr ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll;
    Spelling = LoopHintAttr::Pragma_unroll;
  } else if (PragmaNoUnroll) {
    Option = LoopHintAttr::Unroll;
    Spelling = LoopHintAttr::Pragma_nounroll;
  } else {
    assert(OptionLoc && OptionLoc->Ident &&
           "Attribute must have valid option info.");
    IdentifierInfo *OptionInfo = OptionLoc->Ident;
    Option = llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getName())
                 .Case("vectorize", LoopHintAttr::Vectorize)
                 .Case("vectorize_width", LoopHintAttr::VectorizeWidth)
                 .Case("interleave", LoopHintAttr::Interleave)
                 .Case("interleave_count", LoopHintAttr::InterleaveCount)
                 .Case("unroll", LoopHintAttr::Unroll)
                 .Case("unroll_count", LoopHintAttr::UnrollCount)
                 .Default(LoopHintAttr::Vectorize);
    Spelling = LoopHintAttr::Pragma_clang_loop;
  }

  int ValueInt = 1;
  LoopHintAttr::LoopHintState State = LoopHintAttr::Default;
  if (PragmaNoUnroll) {
    State = LoopHintAttr::Disable;
  } else if (Option == LoopHintAttr::VectorizeWidth ||
             Option == LoopHintAttr::InterleaveCount ||
             Option == LoopHintAttr::UnrollCount) {
    // FIXME: We should support template parameters for the loop hint value.
    // See bug report #19610.
    llvm::APSInt ValueAPS;
    if (!ValueExpr || !ValueExpr->isIntegerConstantExpr(ValueAPS, S.Context) ||
        (ValueInt = ValueAPS.getSExtValue()) < 1) {
      S.Diag(A.getLoc(), diag::err_pragma_loop_invalid_value);
      return nullptr;
    }
  } else if (Option == LoopHintAttr::Vectorize ||
             Option == LoopHintAttr::Interleave ||
             Option == LoopHintAttr::Unroll) {
    // Default state is assumed if StateLoc is not specified, such as with
    // '#pragma unroll'.
    if (StateLoc && StateLoc->Ident) {
      if (StateLoc->Ident->isStr("disable"))
        State = LoopHintAttr::Disable;
      else
        State = LoopHintAttr::Enable;
    }
  }

  return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, State,
                                      ValueInt, A.getRange());
}

static void
CheckForIncompatibleAttributes(Sema &S,
                               const SmallVectorImpl<const Attr *> &Attrs) {
  // There are 3 categories of loop hints attributes: vectorize, interleave,
  // and unroll. Each comes in two variants: a state form and a numeric form.
  // The state form selectively defaults/enables/disables the transformation
  // for the loop (for unroll, default indicates full unrolling rather than
  // enabling the transformation).  The numeric form form provides an integer
  // hint (for example, unroll count) to the transformer. The following array
  // accumulates the hints encountered while iterating through the attributes
  // to check for compatibility.
  struct {
    const LoopHintAttr *StateAttr;
    const LoopHintAttr *NumericAttr;
  } HintAttrs[] = {{nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}};

  for (const auto *I : Attrs) {
    const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);

    // Skip non loop hint attributes
    if (!LH)
      continue;

    int Option = LH->getOption();
    int Category;
    enum { Vectorize, Interleave, Unroll };
    switch (Option) {
    case LoopHintAttr::Vectorize:
    case LoopHintAttr::VectorizeWidth:
      Category = Vectorize;
      break;
    case LoopHintAttr::Interleave:
    case LoopHintAttr::InterleaveCount:
      Category = Interleave;
      break;
    case LoopHintAttr::Unroll:
    case LoopHintAttr::UnrollCount:
      Category = Unroll;
      break;
    };

    auto &CategoryState = HintAttrs[Category];
    const LoopHintAttr *PrevAttr;
    if (Option == LoopHintAttr::Vectorize ||
        Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll) {
      // Enable|disable hint.  For example, vectorize(enable).
      PrevAttr = CategoryState.StateAttr;
      CategoryState.StateAttr = LH;
    } else {
      // Numeric hint.  For example, vectorize_width(8).
      PrevAttr = CategoryState.NumericAttr;
      CategoryState.NumericAttr = LH;
    }

    PrintingPolicy Policy(S.Context.getLangOpts());
    SourceLocation OptionLoc = LH->getRange().getBegin();
    if (PrevAttr)
      // Cannot specify same type of attribute twice.
      S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
          << /*Duplicate=*/true << PrevAttr->getDiagnosticName(Policy)
          << LH->getDiagnosticName(Policy);

    if (CategoryState.StateAttr && CategoryState.NumericAttr &&
        (Category == Unroll ||
         CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) {
      // Disable hints are not compatible with numeric hints of the same
      // category.  As a special case, numeric unroll hints are also not
      // compatible with "enable" form of the unroll pragma, unroll(full).
      S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
          << /*Duplicate=*/false
          << CategoryState.StateAttr->getDiagnosticName(Policy)
          << CategoryState.NumericAttr->getDiagnosticName(Policy);
    }
  }
}
a55 2
  case AttributeList::AT_LoopHint:
    return handleLoopHintAttr(S, St, A, Range);
a72 2
  CheckForIncompatibleAttributes(*this, Attrs);

@


1.1.1.5.2.1
log
@Update LLVM to 3.6.1, requested by joerg in ticket 824.
@
text
@d91 1
d98 6
a103 2
    assert(ValueExpr && "Attribute must have a valid value expression.");
    if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart()))
d105 1
d120 1
a120 1
                                      ValueExpr, A.getRange());
@


1.1.1.6
log
@Import Clang 3.6RC1 r227398.
@
text
@d91 1
d98 6
a103 2
    assert(ValueExpr && "Attribute must have a valid value expression.");
    if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart()))
d105 1
d120 1
a120 1
                                      ValueExpr, A.getRange());
@


1.1.1.7
log
@Import Clang 3.8.0rc3 r261930.
@
text
@d68 1
d70 5
a74 4
  LoopHintAttr::OptionType Option;
  LoopHintAttr::LoopHintState State;
  if (PragmaNoUnroll) {
    // #pragma nounroll
a75 13
    Option = LoopHintAttr::Unroll;
    State = LoopHintAttr::Disable;
  } else if (PragmaUnroll) {
    Spelling = LoopHintAttr::Pragma_unroll;
    if (ValueExpr) {
      // #pragma unroll N
      Option = LoopHintAttr::UnrollCount;
      State = LoopHintAttr::Numeric;
    } else {
      // #pragma unroll
      Option = LoopHintAttr::Unroll;
      State = LoopHintAttr::Enable;
    }
a76 2
    // #pragma clang loop ...
    Spelling = LoopHintAttr::Pragma_clang_loop;
d79 2
a80 2
    Option = llvm::StringSwitch<LoopHintAttr::OptionType>(
                 OptionLoc->Ident->getName())
d88 18
a105 11
    if (Option == LoopHintAttr::VectorizeWidth ||
        Option == LoopHintAttr::InterleaveCount ||
        Option == LoopHintAttr::UnrollCount) {
      assert(ValueExpr && "Attribute must have a valid value expression.");
      if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart()))
        return nullptr;
      State = LoopHintAttr::Numeric;
    } else if (Option == LoopHintAttr::Vectorize ||
               Option == LoopHintAttr::Interleave ||
               Option == LoopHintAttr::Unroll) {
      assert(StateLoc && StateLoc->Ident && "Loop hint must have an argument");
d108 1
a108 5
      else if (StateLoc->Ident->isStr("assume_safety"))
        State = LoopHintAttr::AssumeSafety;
      else if (StateLoc->Ident->isStr("full"))
        State = LoopHintAttr::Full;
      else if (StateLoc->Ident->isStr("enable"))
d110 1
a110 4
      else
        llvm_unreachable("bad loop hint argument");
    } else
      llvm_unreachable("bad loop hint");
d140 3
a142 2
    LoopHintAttr::OptionType Option = LH->getOption();
    enum { Vectorize, Interleave, Unroll } Category;
d162 1
a162 1
      // Enable|Disable|AssumeSafety hint.  For example, vectorize(enable).
d184 1
a184 2
      // compatible with enable or full form of the unroll pragma because these
      // directives indicate full unrolling.
@


1.1.1.7.2.1
log
@Sync with HEAD
@
text
@a27 2
  FallThroughAttr Attr(A.getRange(), S.Context,
                       A.getAttributeSpellingListIndex());
d30 1
a30 1
        << Attr.getSpelling() << St->getLocStart();
d38 1
a38 2
  auto *FnScope = S.getCurFunction();
  if (FnScope->SwitchStack.empty()) {
d42 2
a43 9

  // If this is spelled as the standard C++1z attribute, but not in C++1z, warn
  // about using it as an extension.
  if (!S.getLangOpts().CPlusPlus1z && A.isCXX11Attribute() &&
      !A.getScopeName())
    S.Diag(A.getLoc(), diag::ext_cxx1z_attr) << A.getName();

  FnScope->setHasFallthroughStmt();
  return ::new (S.Context) auto(Attr);
a99 1
                 .Case("distribute", LoopHintAttr::Distribute)
d110 1
a110 2
               Option == LoopHintAttr::Unroll ||
               Option == LoopHintAttr::Distribute) {
d133 8
a140 8
  // There are 4 categories of loop hints attributes: vectorize, interleave,
  // unroll and distribute. Except for distribute they come in two variants: a
  // state form and a numeric form.  The state form selectively
  // defaults/enables/disables the transformation for the loop (for unroll,
  // default indicates full unrolling rather than enabling the transformation).
  // The numeric form form provides an integer hint (for example, unroll count)
  // to the transformer. The following array accumulates the hints encountered
  // while iterating through the attributes to check for compatibility.
d144 1
a144 4
  } HintAttrs[] = {{nullptr, nullptr},
                   {nullptr, nullptr},
                   {nullptr, nullptr},
                   {nullptr, nullptr}};
d154 1
a154 1
    enum { Vectorize, Interleave, Unroll, Distribute } Category;
a167 4
    case LoopHintAttr::Distribute:
      // Perform the check for duplicated 'distribute' hints.
      Category = Distribute;
      break;
d173 1
a173 2
        Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll ||
        Option == LoopHintAttr::Distribute) {
a205 42
static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const AttributeList &A,
                                    SourceRange Range) {
  // Although the feature was introduced only in OpenCL C v2.0 s6.11.5, it's
  // useful for OpenCL 1.x too and doesn't require HW support.
  // opencl_unroll_hint can have 0 arguments (compiler
  // determines unrolling factor) or 1 argument (the unroll factor provided
  // by the user).

  unsigned NumArgs = A.getNumArgs();

  if (NumArgs > 1) {
    S.Diag(A.getLoc(), diag::err_attribute_too_many_arguments) << A.getName()
                                                               << 1;
    return nullptr;
  }

  unsigned UnrollFactor = 0;

  if (NumArgs == 1) {
    Expr *E = A.getArgAsExpr(0);
    llvm::APSInt ArgVal(32);

    if (!E->isIntegerConstantExpr(ArgVal, S.Context)) {
      S.Diag(A.getLoc(), diag::err_attribute_argument_type)
          << A.getName() << AANT_ArgumentIntegerConstant << E->getSourceRange();
      return nullptr;
    }

    int Val = ArgVal.getSExtValue();

    if (Val <= 0) {
      S.Diag(A.getRange().getBegin(),
             diag::err_attribute_requires_positive_integer)
          << A.getName();
      return nullptr;
    }
    UnrollFactor = Val;
  }

  return OpenCLUnrollHintAttr::CreateImplicit(S.Context, UnrollFactor);
}

a217 2
  case AttributeList::AT_OpenCLUnrollHint:
    return handleOpenCLUnrollHint(S, St, A, Range);
d221 1
a221 1
    S.Diag(A.getRange().getBegin(), diag::err_decl_attribute_invalid_on_stmt)
@


1.1.1.8
log
@Import Clang pre-4.0.0 r291444.
@
text
@a27 2
  FallThroughAttr Attr(A.getRange(), S.Context,
                       A.getAttributeSpellingListIndex());
d30 1
a30 1
        << Attr.getSpelling() << St->getLocStart();
d38 1
a38 2
  auto *FnScope = S.getCurFunction();
  if (FnScope->SwitchStack.empty()) {
d42 2
a43 9

  // If this is spelled as the standard C++1z attribute, but not in C++1z, warn
  // about using it as an extension.
  if (!S.getLangOpts().CPlusPlus1z && A.isCXX11Attribute() &&
      !A.getScopeName())
    S.Diag(A.getLoc(), diag::ext_cxx1z_attr) << A.getName();

  FnScope->setHasFallthroughStmt();
  return ::new (S.Context) auto(Attr);
a99 1
                 .Case("distribute", LoopHintAttr::Distribute)
d110 1
a110 2
               Option == LoopHintAttr::Unroll ||
               Option == LoopHintAttr::Distribute) {
d133 8
a140 8
  // There are 4 categories of loop hints attributes: vectorize, interleave,
  // unroll and distribute. Except for distribute they come in two variants: a
  // state form and a numeric form.  The state form selectively
  // defaults/enables/disables the transformation for the loop (for unroll,
  // default indicates full unrolling rather than enabling the transformation).
  // The numeric form form provides an integer hint (for example, unroll count)
  // to the transformer. The following array accumulates the hints encountered
  // while iterating through the attributes to check for compatibility.
d144 1
a144 4
  } HintAttrs[] = {{nullptr, nullptr},
                   {nullptr, nullptr},
                   {nullptr, nullptr},
                   {nullptr, nullptr}};
d154 1
a154 1
    enum { Vectorize, Interleave, Unroll, Distribute } Category;
a167 4
    case LoopHintAttr::Distribute:
      // Perform the check for duplicated 'distribute' hints.
      Category = Distribute;
      break;
d173 1
a173 2
        Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll ||
        Option == LoopHintAttr::Distribute) {
a205 42
static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const AttributeList &A,
                                    SourceRange Range) {
  // Although the feature was introduced only in OpenCL C v2.0 s6.11.5, it's
  // useful for OpenCL 1.x too and doesn't require HW support.
  // opencl_unroll_hint can have 0 arguments (compiler
  // determines unrolling factor) or 1 argument (the unroll factor provided
  // by the user).

  unsigned NumArgs = A.getNumArgs();

  if (NumArgs > 1) {
    S.Diag(A.getLoc(), diag::err_attribute_too_many_arguments) << A.getName()
                                                               << 1;
    return nullptr;
  }

  unsigned UnrollFactor = 0;

  if (NumArgs == 1) {
    Expr *E = A.getArgAsExpr(0);
    llvm::APSInt ArgVal(32);

    if (!E->isIntegerConstantExpr(ArgVal, S.Context)) {
      S.Diag(A.getLoc(), diag::err_attribute_argument_type)
          << A.getName() << AANT_ArgumentIntegerConstant << E->getSourceRange();
      return nullptr;
    }

    int Val = ArgVal.getSExtValue();

    if (Val <= 0) {
      S.Diag(A.getRange().getBegin(),
             diag::err_attribute_requires_positive_integer)
          << A.getName();
      return nullptr;
    }
    UnrollFactor = Val;
  }

  return OpenCLUnrollHintAttr::CreateImplicit(S.Context, UnrollFactor);
}

a217 2
  case AttributeList::AT_OpenCLUnrollHint:
    return handleOpenCLUnrollHint(S, St, A, Range);
d221 1
a221 1
    S.Diag(A.getRange().getBegin(), diag::err_decl_attribute_invalid_on_stmt)
@


1.1.1.9
log
@Import clang r309604 from branches/release_50
@
text
@a55 25
static Attr *handleSuppressAttr(Sema &S, Stmt *St, const AttributeList &A,
                                SourceRange Range) {
  if (A.getNumArgs() < 1) {
    S.Diag(A.getLoc(), diag::err_attribute_too_few_arguments)
        << A.getName() << 1;
    return nullptr;
  }

  std::vector<StringRef> DiagnosticIdentifiers;
  for (unsigned I = 0, E = A.getNumArgs(); I != E; ++I) {
    StringRef RuleName;

    if (!S.checkStringLiteralArgumentAttr(A, I, RuleName, nullptr))
      return nullptr;

    // FIXME: Warn if the rule name is unknown. This is tricky because only
    // clang-tidy knows about available rules.
    DiagnosticIdentifiers.push_back(RuleName);
  }

  return ::new (S.Context) SuppressAttr(
      A.getRange(), S.Context, DiagnosticIdentifiers.data(),
      DiagnosticIdentifiers.size(), A.getAttributeSpellingListIndex());
}

a281 2
  case AttributeList::AT_Suppress:
    return handleSuppressAttr(S, St, A, Range);
@


1.1.1.9.4.1
log
@Sync with HEAD
@
text
@d26 1
a26 1
static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A,
d46 1
a46 1
  // If this is spelled as the standard C++17 attribute, but not in C++17, warn
d48 1
a48 1
  if (!S.getLangOpts().CPlusPlus17 && A.isCXX11Attribute() &&
d50 1
a50 1
    S.Diag(A.getLoc(), diag::ext_cxx17_attr) << A.getName();
d56 1
a56 1
static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A,
d81 1
a81 1
static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
d103 1
a103 2
  LoopHintAttr::Spelling Spelling =
      LoopHintAttr::Spelling(A.getAttributeSpellingListIndex());
d108 1
d112 1
d124 1
d251 1
a251 1
static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
d293 1
a293 1
static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
d296 1
a296 1
  case ParsedAttr::UnknownAttribute:
d301 1
a301 1
  case ParsedAttr::AT_FallThrough:
d303 1
a303 1
  case ParsedAttr::AT_LoopHint:
d305 1
a305 1
  case ParsedAttr::AT_OpenCLUnrollHint:
d307 1
a307 1
  case ParsedAttr::AT_Suppress:
d318 1
a318 2
StmtResult Sema::ProcessStmtAttributes(Stmt *S,
                                       const ParsedAttributesView &AttrList,
d321 2
a322 2
  for (const ParsedAttr &AL : AttrList) {
    if (Attr *a = ProcessStmtAttribute(*this, S, AL, Range))
@


1.1.1.9.4.2
log
@Mostly merge changes from HEAD upto 20200411
@
text
@@


1.1.1.9.2.1
log
@Sync with HEAD
@
text
@d26 1
a26 1
static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A,
d46 1
a46 1
  // If this is spelled as the standard C++17 attribute, but not in C++17, warn
d48 1
a48 1
  if (!S.getLangOpts().CPlusPlus17 && A.isCXX11Attribute() &&
d50 1
a50 1
    S.Diag(A.getLoc(), diag::ext_cxx17_attr) << A.getName();
d56 1
a56 1
static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A,
d81 1
a81 1
static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
d103 1
a103 2
  LoopHintAttr::Spelling Spelling =
      LoopHintAttr::Spelling(A.getAttributeSpellingListIndex());
d108 1
d112 1
d124 1
d251 1
a251 1
static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
d293 1
a293 1
static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
d296 1
a296 1
  case ParsedAttr::UnknownAttribute:
d301 1
a301 1
  case ParsedAttr::AT_FallThrough:
d303 1
a303 1
  case ParsedAttr::AT_LoopHint:
d305 1
a305 1
  case ParsedAttr::AT_OpenCLUnrollHint:
d307 1
a307 1
  case ParsedAttr::AT_Suppress:
d318 1
a318 2
StmtResult Sema::ProcessStmtAttributes(Stmt *S,
                                       const ParsedAttributesView &AttrList,
d321 2
a322 2
  for (const ParsedAttr &AL : AttrList) {
    if (Attr *a = ProcessStmtAttribute(*this, S, AL, Range))
@


1.1.1.10
log
@Import clang r337282 from trunk
@
text
@d26 1
a26 1
static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A,
d46 1
a46 1
  // If this is spelled as the standard C++17 attribute, but not in C++17, warn
d48 1
a48 1
  if (!S.getLangOpts().CPlusPlus17 && A.isCXX11Attribute() &&
d50 1
a50 1
    S.Diag(A.getLoc(), diag::ext_cxx17_attr) << A.getName();
d56 1
a56 1
static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A,
d81 1
a81 1
static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
d103 1
a103 2
  LoopHintAttr::Spelling Spelling =
      LoopHintAttr::Spelling(A.getAttributeSpellingListIndex());
d108 1
d112 1
d124 1
d251 1
a251 1
static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
d293 1
a293 1
static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
d296 1
a296 1
  case ParsedAttr::UnknownAttribute:
d301 1
a301 1
  case ParsedAttr::AT_FallThrough:
d303 1
a303 1
  case ParsedAttr::AT_LoopHint:
d305 1
a305 1
  case ParsedAttr::AT_OpenCLUnrollHint:
d307 1
a307 1
  case ParsedAttr::AT_Suppress:
d318 1
a318 2
StmtResult Sema::ProcessStmtAttributes(Stmt *S,
                                       const ParsedAttributesView &AttrList,
d321 2
a322 2
  for (const ParsedAttr &AL : AttrList) {
    if (Attr *a = ProcessStmtAttribute(*this, S, AL, Range))
@


1.1.1.11
log
@Mark old LLVM instance as dead.
@
text
@@


1.1.1.5.4.1
log
@file SemaStmtAttr.cpp was added on branch tls-maxphys on 2014-08-19 23:47:30 +0000
@
text
@d1 234
@


1.1.1.5.4.2
log
@Rebase to HEAD as of a few days ago.
@
text
@a0 234
//===--- SemaStmtAttr.cpp - Statement Attribute Handling ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements stmt-related attribute processing.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/LoopHint.h"
#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/StringExtras.h"

using namespace clang;
using namespace sema;

static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
                                   SourceRange Range) {
  if (!isa<NullStmt>(St)) {
    S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target)
        << St->getLocStart();
    if (isa<SwitchCase>(St)) {
      SourceLocation L = S.getLocForEndOfToken(Range.getEnd());
      S.Diag(L, diag::note_fallthrough_insert_semi_fixit)
          << FixItHint::CreateInsertion(L, ";");
    }
    return nullptr;
  }
  if (S.getCurFunction()->SwitchStack.empty()) {
    S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_outside_switch);
    return nullptr;
  }
  return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context,
                                           A.getAttributeSpellingListIndex());
}

static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
                                SourceRange) {
  IdentifierLoc *PragmaNameLoc = A.getArgAsIdent(0);
  IdentifierLoc *OptionLoc = A.getArgAsIdent(1);
  IdentifierLoc *StateLoc = A.getArgAsIdent(2);
  Expr *ValueExpr = A.getArgAsExpr(3);

  bool PragmaUnroll = PragmaNameLoc->Ident->getName() == "unroll";
  bool PragmaNoUnroll = PragmaNameLoc->Ident->getName() == "nounroll";
  if (St->getStmtClass() != Stmt::DoStmtClass &&
      St->getStmtClass() != Stmt::ForStmtClass &&
      St->getStmtClass() != Stmt::CXXForRangeStmtClass &&
      St->getStmtClass() != Stmt::WhileStmtClass) {
    const char *Pragma =
        llvm::StringSwitch<const char *>(PragmaNameLoc->Ident->getName())
            .Case("unroll", "#pragma unroll")
            .Case("nounroll", "#pragma nounroll")
            .Default("#pragma clang loop");
    S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
    return nullptr;
  }

  LoopHintAttr::OptionType Option;
  LoopHintAttr::Spelling Spelling;
  if (PragmaUnroll) {
    Option = ValueExpr ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll;
    Spelling = LoopHintAttr::Pragma_unroll;
  } else if (PragmaNoUnroll) {
    Option = LoopHintAttr::Unroll;
    Spelling = LoopHintAttr::Pragma_nounroll;
  } else {
    assert(OptionLoc && OptionLoc->Ident &&
           "Attribute must have valid option info.");
    IdentifierInfo *OptionInfo = OptionLoc->Ident;
    Option = llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getName())
                 .Case("vectorize", LoopHintAttr::Vectorize)
                 .Case("vectorize_width", LoopHintAttr::VectorizeWidth)
                 .Case("interleave", LoopHintAttr::Interleave)
                 .Case("interleave_count", LoopHintAttr::InterleaveCount)
                 .Case("unroll", LoopHintAttr::Unroll)
                 .Case("unroll_count", LoopHintAttr::UnrollCount)
                 .Default(LoopHintAttr::Vectorize);
    Spelling = LoopHintAttr::Pragma_clang_loop;
  }

  int ValueInt = 1;
  LoopHintAttr::LoopHintState State = LoopHintAttr::Default;
  if (PragmaNoUnroll) {
    State = LoopHintAttr::Disable;
  } else if (Option == LoopHintAttr::VectorizeWidth ||
             Option == LoopHintAttr::InterleaveCount ||
             Option == LoopHintAttr::UnrollCount) {
    // FIXME: We should support template parameters for the loop hint value.
    // See bug report #19610.
    llvm::APSInt ValueAPS;
    if (!ValueExpr || !ValueExpr->isIntegerConstantExpr(ValueAPS, S.Context) ||
        (ValueInt = ValueAPS.getSExtValue()) < 1) {
      S.Diag(A.getLoc(), diag::err_pragma_loop_invalid_value);
      return nullptr;
    }
  } else if (Option == LoopHintAttr::Vectorize ||
             Option == LoopHintAttr::Interleave ||
             Option == LoopHintAttr::Unroll) {
    // Default state is assumed if StateLoc is not specified, such as with
    // '#pragma unroll'.
    if (StateLoc && StateLoc->Ident) {
      if (StateLoc->Ident->isStr("disable"))
        State = LoopHintAttr::Disable;
      else
        State = LoopHintAttr::Enable;
    }
  }

  return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, State,
                                      ValueInt, A.getRange());
}

static void
CheckForIncompatibleAttributes(Sema &S,
                               const SmallVectorImpl<const Attr *> &Attrs) {
  // There are 3 categories of loop hints attributes: vectorize, interleave,
  // and unroll. Each comes in two variants: a state form and a numeric form.
  // The state form selectively defaults/enables/disables the transformation
  // for the loop (for unroll, default indicates full unrolling rather than
  // enabling the transformation).  The numeric form form provides an integer
  // hint (for example, unroll count) to the transformer. The following array
  // accumulates the hints encountered while iterating through the attributes
  // to check for compatibility.
  struct {
    const LoopHintAttr *StateAttr;
    const LoopHintAttr *NumericAttr;
  } HintAttrs[] = {{nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}};

  for (const auto *I : Attrs) {
    const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);

    // Skip non loop hint attributes
    if (!LH)
      continue;

    int Option = LH->getOption();
    int Category;
    enum { Vectorize, Interleave, Unroll };
    switch (Option) {
    case LoopHintAttr::Vectorize:
    case LoopHintAttr::VectorizeWidth:
      Category = Vectorize;
      break;
    case LoopHintAttr::Interleave:
    case LoopHintAttr::InterleaveCount:
      Category = Interleave;
      break;
    case LoopHintAttr::Unroll:
    case LoopHintAttr::UnrollCount:
      Category = Unroll;
      break;
    };

    auto &CategoryState = HintAttrs[Category];
    const LoopHintAttr *PrevAttr;
    if (Option == LoopHintAttr::Vectorize ||
        Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll) {
      // Enable|disable hint.  For example, vectorize(enable).
      PrevAttr = CategoryState.StateAttr;
      CategoryState.StateAttr = LH;
    } else {
      // Numeric hint.  For example, vectorize_width(8).
      PrevAttr = CategoryState.NumericAttr;
      CategoryState.NumericAttr = LH;
    }

    PrintingPolicy Policy(S.Context.getLangOpts());
    SourceLocation OptionLoc = LH->getRange().getBegin();
    if (PrevAttr)
      // Cannot specify same type of attribute twice.
      S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
          << /*Duplicate=*/true << PrevAttr->getDiagnosticName(Policy)
          << LH->getDiagnosticName(Policy);

    if (CategoryState.StateAttr && CategoryState.NumericAttr &&
        (Category == Unroll ||
         CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) {
      // Disable hints are not compatible with numeric hints of the same
      // category.  As a special case, numeric unroll hints are also not
      // compatible with "enable" form of the unroll pragma, unroll(full).
      S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
          << /*Duplicate=*/false
          << CategoryState.StateAttr->getDiagnosticName(Policy)
          << CategoryState.NumericAttr->getDiagnosticName(Policy);
    }
  }
}

static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
                                  SourceRange Range) {
  switch (A.getKind()) {
  case AttributeList::UnknownAttribute:
    S.Diag(A.getLoc(), A.isDeclspecAttribute() ?
           diag::warn_unhandled_ms_attribute_ignored :
           diag::warn_unknown_attribute_ignored) << A.getName();
    return nullptr;
  case AttributeList::AT_FallThrough:
    return handleFallThroughAttr(S, St, A, Range);
  case AttributeList::AT_LoopHint:
    return handleLoopHintAttr(S, St, A, Range);
  default:
    // if we're here, then we parsed a known attribute, but didn't recognize
    // it as a statement attribute => it is declaration attribute
    S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt)
        << A.getName() << St->getLocStart();
    return nullptr;
  }
}

StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
                                       SourceRange Range) {
  SmallVector<const Attr*, 8> Attrs;
  for (const AttributeList* l = AttrList; l; l = l->getNext()) {
    if (Attr *a = ProcessStmtAttribute(*this, S, *l, Range))
      Attrs.push_back(a);
  }

  CheckForIncompatibleAttributes(*this, Attrs);

  if (Attrs.empty())
    return S;

  return ActOnAttributedStmt(Range.getBegin(), Attrs, S);
}
@


1.1.1.3.4.1
log
@file SemaStmtAttr.cpp was added on branch yamt-pagecache on 2014-05-22 16:18:30 +0000
@
text
@d1 79
@


1.1.1.3.4.2
log
@sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs.  ("Protocol error: too many arguments")
@
text
@a0 79
//===--- SemaStmtAttr.cpp - Statement Attribute Handling ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements stmt-related attribute processing.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/StringExtras.h"

using namespace clang;
using namespace sema;

static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
                                   SourceRange Range) {
  if (!isa<NullStmt>(St)) {
    S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target)
        << St->getLocStart();
    if (isa<SwitchCase>(St)) {
      SourceLocation L = Lexer::getLocForEndOfToken(Range.getEnd(), 0,
                                  S.getSourceManager(), S.getLangOpts());
      S.Diag(L, diag::note_fallthrough_insert_semi_fixit)
          << FixItHint::CreateInsertion(L, ";");
    }
    return 0;
  }
  if (S.getCurFunction()->SwitchStack.empty()) {
    S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_outside_switch);
    return 0;
  }
  return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context,
                                           A.getAttributeSpellingListIndex());
}


static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
                                  SourceRange Range) {
  switch (A.getKind()) {
  case AttributeList::UnknownAttribute:
    S.Diag(A.getLoc(), A.isDeclspecAttribute() ?
           diag::warn_unhandled_ms_attribute_ignored :
           diag::warn_unknown_attribute_ignored) << A.getName();
    return 0;
  case AttributeList::AT_FallThrough:
    return handleFallThroughAttr(S, St, A, Range);
  default:
    // if we're here, then we parsed a known attribute, but didn't recognize
    // it as a statement attribute => it is declaration attribute
    S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt)
        << A.getName() << St->getLocStart();
    return 0;
  }
}

StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
                                       SourceRange Range) {
  SmallVector<const Attr*, 8> Attrs;
  for (const AttributeList* l = AttrList; l; l = l->getNext()) {
    if (Attr *a = ProcessStmtAttribute(*this, S, *l, Range))
      Attrs.push_back(a);
  }

  if (Attrs.empty())
    return S;

  return ActOnAttributedStmt(Range.getBegin(), Attrs, S);
}
@


